# blinc_canvas_kit
> **Part of the [Blinc UI Framework](https://project-blinc.github.io/Blinc)**
>
> This crate is a component of Blinc, a GPU-accelerated UI framework for Rust.
> For full documentation and guides, visit the [Blinc documentation](https://project-blinc.github.io/Blinc).
Interactive canvas toolkit for game editors and node graphs — pan, zoom, spatial indexing, multi-select, marquee selection, and snap-to-grid.
## Overview
`blinc_canvas_kit` provides everything needed to build interactive infinite canvas applications:
- **Viewport Management**: Pan (with momentum), zoom (scroll + pinch), coordinate conversion between screen-space and content-space
- **Spatial Indexing**: Uniform-grid spatial hash for O(1) hit testing and fast range queries, scaling to thousands of elements
- **Multi-Select**: Shift+click to add, Cmd/Ctrl+click to toggle, with selection change callbacks
- **Marquee Selection**: Box-select via tool mode or Shift+drag, with live preview and additive mode
- **Snap-to-Grid**: Round content-space positions to configurable grid spacing
- **Background Patterns**: Infinite viewport-aware dot grid, line grid, and crosshatch patterns with zoom-adaptive density
- **Viewport Culling**: Skip rendering off-screen elements with a simple visibility check
- **Hit Regions**: Register interactive bounding boxes during drawing, with click/hover/drag callbacks
## Quick Start
```rust
use blinc_canvas_kit::prelude::*;
let mut kit = CanvasKit::new("editor")
.with_background(CanvasBackground::dots().with_spacing(25.0))
.with_snap(25.0);
println!("Clicked {id}");
}
});
});
});
// Returns a fully-wired Div with canvas + event handlers
```rust
// Query selection state
let sel = kit.selection();
for id in &sel.selected {
println!("Selected: {id}");
}
// Check individual items (useful in render callbacks for visual feedback)
if kit.is_selected("node_1") {
// Draw highlight
}
// Programmatic selection
kit.set_selection(HashSet::from(["a".into(), "b".into()]));
kit.clear_selection();
```
### Snap-to-Grid
```rust
// Enable snapping
let kit = CanvasKit::new("editor").with_snap(25.0);
// Use in drag callbacks for precise positioning
let snapped = kit.snap_point(target);
// Apply snapped position to your element
});
```
### Viewport Culling
```rust
All state persists across UI rebuilds via `BlincContextState` keyed storage. The spatial index is rebuilt each frame during the render callback (via `hit_rect()` calls), while selection, viewport, and interaction state persist.
| `viewport` | Pan/zoom state, coordinate conversion, visibility testing |
| `pan` | Momentum panning with EMA velocity tracking |
| `zoom` | Scroll and pinch zoom handlers |
| `spatial` | Uniform-grid spatial hash for hit testing and range queries |
| `selection` | Multi-select state, marquee drag, tool modes |
| `snap` | Grid snapping for content-space coordinates |
| `background` | Infinite viewport-aware pattern rendering |
| `hit` | Hit region types and event structs |