# CLAUDE.md This file provides guidance to Claude Code when working with this repository. ## Project Overview **pastel-wasm** is a WebAssembly color manipulation library built with Rust. It provides comprehensive color operations directly in the browser with zero network latency. **Key Stats:** - Bundle size: 132KB (WASM) - Language: Rust + WebAssembly - Target: Modern browsers with WASM support - Dependencies: Minimal (wasm-bindgen, serde, rand, getrandom) ## Architecture ### Project Structure ``` pastel-wasm/ ├── src/ │ ├── lib.rs # Main WASM bindings and exported functions │ ├── color.rs # Core color type and conversions │ └── named.rs # Named colors database (148 CSS/X11 colors) ├── pkg/ # Build output (generated by wasm-pack) │ ├── pastel_wasm.js │ ├── pastel_wasm.d.ts │ └── pastel_wasm_bg.wasm ├── Cargo.toml # Rust dependencies and configuration ├── package.json # NPM package configuration ├── README.md # User documentation └── example.html # Interactive demo ## Color Implementation ### Color Type (`src/color.rs`) The core `Color` struct represents colors in RGB space (0.0-1.0 range): ```rust pub struct Color { pub r: f64, pub g: f64, pub b: f64, pub a: f64, } ``` **Key Methods:** - `parse(s: &str)` - Universal color parser (hex, rgb, hsl, named) - `to_hex()` - Convert to hex string - `to_hsl()`, `to_hsv()`, `to_lab()`, `to_lch()` - Color space conversions - `lighten()`, `darken()`, `saturate()`, `desaturate()` - Adjustments - `rotate_hue()`, `complement()`, `mix()` - Transformations - `text_color()`, `contrast_ratio()` - Accessibility helpers - `simulate_protanopia/deuteranopia/tritanopia()` - Color blindness - `distance_cie76()`, `distance_ciede2000()` - Perceptual distance ### Color Space Conversions **Implemented color spaces:** - RGB ↔ HSL (Hue, Saturation, Lightness) - RGB ↔ HSV (Hue, Saturation, Value) - RGB → XYZ → Lab (CIELab, perceptually uniform) - Lab → LCH (Lightness, Chroma, Hue) **Conversion accuracy:** - Uses D65 illuminant for XYZ conversions - Implements proper gamma correction for sRGB - Perceptually accurate Lab/LCH calculations ### Named Colors (`src/named.rs`) Contains 148 CSS/X11 named colors as const data: ```rust pub const NAMED_COLORS: &[NamedColor] = &[ NamedColor { name: "red", hex: "#ff0000" }, // ... 147 more ]; ``` ## WASM Bindings (`src/lib.rs`) All exported functions are annotated with `#[wasm_bindgen]`: **Categories:** 1. **Color Information** - `parse_color()` 2. **Color Manipulation** - `lighten_color()`, `darken_color()`, etc. 3. **Color Generation** - `generate_random_colors()`, `generate_gradient()`, `generate_palette()` 4. **Accessibility** - `get_text_color()`, `simulate_*()`, `calculate_contrast()` 5. **Named Colors** - `get_all_named_colors()`, `search_named_colors()` 6. **Utilities** - `color_distance()`, `version()` **Return types:** - Simple functions return `Result` (hex colors) - Complex functions return `Result` (serialized objects) - Uses `serde_wasm_bindgen` for JS ↔ Rust serialization ## Building ### Prerequisites ```bash # Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install wasm-pack cargo install wasm-pack ``` ### Build Commands ```bash # Build for bundler (Webpack, Rollup, Vite) wasm-pack build --target bundler --out-dir pkg # Build for web (vanilla JS) wasm-pack build --target web --out-dir pkg-web # Build for Node.js wasm-pack build --target nodejs --out-dir pkg-node # Build all targets npm run build:all ``` ### Build Configuration **Cargo.toml optimizations:** - `opt-level = "s"` - Optimize for size - `lto = true` - Link-time optimization - `codegen-units = 1` - Better optimization - `strip = true` - Remove debug symbols **wasm-opt flags:** - `--enable-bulk-memory` - Memory operations - `--enable-nontrapping-float-to-int` - Modern WASM features - `-Os` - Optimize for size ## Dependencies **Core dependencies:** - `wasm-bindgen = "0.2"` - Rust ↔ JavaScript interop - `serde = "1.0"` - Serialization framework - `serde-wasm-bindgen = "0.6"` - JS object serialization - `rand = "0.8"` - Random number generation - `getrandom = { version = "0.2", features = ["js"] }` - WASM-compatible RNG - `js-sys = "0.3"` - JavaScript standard library bindings - `web-sys = "0.3"` - Web API bindings - `console_error_panic_hook = "0.1"` - Better panic messages in browser ## Testing ```bash # Run tests in headless browsers wasm-pack test --headless --firefox --chrome # Run tests in specific browser wasm-pack test --firefox wasm-pack test --chrome ``` ## Publishing ```bash # Build and test npm run build npm test # Publish to npm wasm-pack pack wasm-pack publish ``` ## Integration with pastel-ui The `pastel-ui` Next.js application uses this WASM module instead of the REST API: **Migration steps:** 1. Install: `npm install pastel-wasm` 2. Import: `import * as pastel from 'pastel-wasm'` 3. Initialize: Call `await pastel.init()` on app load 4. Replace API calls with direct WASM functions 5. Update types (WASM returns simpler structures than API) **Benefits for pastel-ui:** - **Performance**: 0ms latency vs 50-200ms API calls - **Reliability**: No network errors, works offline - **Cost**: Zero server costs, no rate limiting - **Privacy**: Color data never leaves the browser ## Development Workflow ### Adding a New Function 1. **Implement in color.rs:** ```rust impl Color { pub fn my_new_operation(&self) -> Self { // implementation } } ``` 2. **Add WASM binding in lib.rs:** ```rust #[wasm_bindgen] pub fn my_new_operation(color: &str) -> Result { let c = Color::parse(color).map_err(|e| JsValue::from_str(&e))?; Ok(c.my_new_operation().to_hex()) } ``` 3. **Rebuild:** ```bash wasm-pack build --target bundler --out-dir pkg ``` 4. **Test in example.html:** ```javascript const result = pastel.my_new_operation('#ff0099'); ``` ### Debugging **Rust errors:** ```bash # Check for compile errors cargo check # Run clippy for lints cargo clippy ``` **WASM errors:** - Enable panic hook: `pastel.init()` calls `console_error_panic_hook::set_once()` - Check browser console for panics - Use `console.log()` via `web_sys::console::log_1()` ## Performance Considerations **Fast operations** (< 0.1ms): - Color parsing - Simple manipulations (lighten, darken, saturate) - Color space conversions - Hex formatting **Medium operations** (< 1ms): - Gradient generation (10 steps) - Palette generation - Color distance calculations **Memory:** - Each Color instance: 32 bytes (4 × f64) - Named colors array: ~10KB (static data) - WASM memory grows dynamically as needed ## Common Issues ### Build Fails with "errno not supported" **Cause**: Using pastel library directly (has CLI dependencies) **Solution**: Use custom color implementation (already done) ### wasm-opt validation errors **Cause**: Missing WASM features **Solution**: Add flags in Cargo.toml: ```toml [package.metadata.wasm-pack.profile.release] wasm-opt = ["-Os", "--enable-mutable-globals", "--enable-bulk-memory", "--enable-nontrapping-float-to-int"] ``` ### Random number generation fails in browser **Cause**: Missing JS feature flag for getrandom **Solution**: Add to Cargo.toml: ```toml getrandom = { version = "0.2", features = ["js"] } ``` ## Future Enhancements ### Planned Features - [ ] More color harmony schemes (square, split, analogous) - [ ] Color palettes from images (requires image parsing) - [ ] CMYK color space support - [ ] Color name lookup (closest named color) - [ ] Gradient interpolation in different color spaces (Lab, LCH) - [ ] Batch processing optimizations ### Optimization Opportunities - [ ] SIMD operations for batch processing - [ ] Lazy loading of named colors - [ ] Memoization of expensive calculations - [ ] WebWorker support for heavy operations ## Resources - [wasm-bindgen Book](https://rustwasm.github.io/wasm-bindgen/) - [Color Science](https://en.wikipedia.org/wiki/CIE_1931_color_space) - [CIEDE2000 Algorithm](https://en.wikipedia.org/wiki/Color_difference#CIEDE2000) - [WCAG Contrast](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html) --- **Project Status**: Production-ready **Last Updated**: 2025-01-17