cocoanut 0.2.3

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 = state(0);
    let inc = count.clone();
    let dec = count.clone();

    app("Counter")
        .size(400.0, 300.0)
        .build()
        .root(
            View::vstack()
                .child(View::text("Counter").bold().font_size(20.0))
                .child(View::label(&format!("Count: {}", count.get())).font_size(32.0))
                .child(View::hstack()
                    .child(View::button("+").on_click_fn(move || inc.increment()))
                    .child(View::button("-").on_click_fn(move || dec.decrement()))
                )
        )
        .run()
}
```

## What's New in v0.3.0

### Direct Closures
No more manual event ID management:
```rust
// Before (v0.2.0)
event::register(1, || count.set(count.get() + 1));
View::button("+").on_click(1)

// After (v0.3.0)
View::button("+").on_click_fn(|| count.increment())
```

### State Helpers
```rust
let count = state(0);
count.increment();  // +1
count.decrement();  // -1
count.reset();      // → 0

let text = state(String::new());
text.append("hello");
text.clear();

let flag = state(false);
flag.toggle();
```

### Styling DSL
```rust
use cocoanut::prelude::*;

let btn_style = style()
    .width(100.0)
    .height(40.0)
    .padding(10.0)
    .background(color("blue"))
    .foreground("white")
    .corner_radius(8.0);

View::button("Click Me").styled(&btn_style)
```

### Component Macros
```rust
component! {
    header,
    View::hstack()
        .child(View::text("My App").bold())
        .child(View::spacer())
        .child(View::button("Settings"))
}

stateful_component! {
    Counter {
        count: State<i64>,
        label: String,
    } => |this| {
        View::vstack()
            .child(View::text(&this.label))
            .child(View::button("+").on_click_fn(move || this.count.increment()))
    }
}
```

### Async Support
```rust
View::button("Fetch Data")
    .on_click_async(|| async {
        let data = fetch_from_api().await;
        state.set(data);
    })
```

### CLI Tool
```bash
# Install
cd cli && cargo install --path .

# Create new project
cocoanut new myapp
cd myapp && cargo run

# Development
cocoanut run --watch    # Hot reload
cocoanut build --release
```

## Architecture

12 source files. ~4000 lines. 32 view types. Extensive unit tests. Type-safe APIs.

```
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
menu.rs          → Menu bar with action dispatch
layout.rs        → Auto Layout support (NSLayoutConstraint)
native.rs        → Native view properties & utilities
delegate.rs      → Delegate patterns for native controls
component.rs     → Component macros
style.rs         → CSS-like styling DSL
async_support.rs → Async/await support
```

## 32 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
- **Native Controls**: SegmentedControl, ComboBox, SearchField, Stepper, LevelIndicator, PathControl
- **Extensible**: Custom

## Features

### Core Features
- **Reactive State** — `State<T>` with `on_change` listeners
- **Direct Closures** — `on_click_fn(|| ...)` without manual IDs
- **Event System** — `event::register(id, closure)` + ObjC target/action dispatch
- **Dark Mode** — `.dark()` / `.light()` / `set_appearance()` at runtime
- **Accessibility** — `.accessibility("label")` on any view
- **Style Modifiers** — `.width()`, `.bold()`, `.background()`, `.on_click()`
- **CSS-like Styling** — `style().width(100).padding(10).background("blue")`
- **JSON Serializable** — `ViewDesc` for debugging/bridging

### Native Cocoa Integration
- **Auto Layout** — NSLayoutConstraint support with type-safe API
- **Native Properties** — Direct access to shadows, layers, corner radius, opacity
- **Responder Chain** — First responder management and key view navigation
- **Delegate Patterns** — TableView data sources, TextField delegates
- **Animation Support** — Native AppKit animations
- **Pasteboard** — Clipboard operations (copy/paste)
- **Window Management** — Window level, alpha, background color

See [NATIVE_COCOA_IMPROVEMENTS.md](NATIVE_COCOA_IMPROVEMENTS.md) for detailed documentation.

## 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 view types + new API
cargo run --example native_features  # native Cocoa integration
```

## Developing

`cargo test` — full library tests (AppKit stubs only under `cfg(test)`). `cargo build --workspace` includes the optional CLI crate.

## License

Apache-2.0