Add beautify tool endpoint to OpenAPI spec with full parameter
documentation. Add tool to REST API docs Layout & Composition table.
Update tool count from 49 to 50 across README, docs homepage,
architecture docs, VitePress config, OpenAPI spec, and LLM docs
generator.
Custom route handler supporting template mode (JSON body with templateId)
and custom image mode (multipart upload). Registers process function for
pipeline compatibility. Includes 18 integration tests.
Root cause analysis of the magic wand bug revealed the same dispatch
pattern affected 13 other tools:
- 8 tools (eyedropper, clone stamp, dodge, burn, sponge, blur brush,
sharpen brush, smudge) had hook implementations but were never
imported or wired into the canvas toolMap -- clicking did nothing
- Selection type (rect/ellipse/lasso) was never synced from the global
activeTool to the selection hook's internal state, so marquee-ellipse
and lasso tools always produced rectangular selections
- Selection drag preview was hardcoded to Rect instead of using the
existing ActiveSelectionPreview component
- Zoom tool click did nothing (now zooms in on click, out on alt+click)
- Magic wand dispatched to generic selection drag instead of flood fill
- Add ppm/pgm/pbm to CLI_DECODED_FORMATS with Sharp-first, ImageMagick fallback
- Create sample.qoi test fixture (10x10 solid color)
- Add QOI to format-matrix test FORMAT_SAMPLES
- Mark PPM/PGM/PBM as needsCliDecoder in tests (Sharp doesn't support them natively)
- CropOverlay: rendered in its own Layer when crop tool is active,
cropState auto-initialized when switching to crop tool
- SelectionOverlay: marching ants rendered for active selections,
selection tool mouse events dispatched through canvas handler
- TransformToolTransformer: rendered when transform tool is active
- Selection tool handlers wired for marquee-rect, marquee-ellipse,
lasso-free, lasso-poly, and magic-wand tools
- Active selection preview rect shown while dragging
- CropOverlay: rendered in its own Layer when crop tool is active,
cropState auto-initialized when switching to crop tool
- SelectionOverlay: marching ants rendered for active selections,
selection tool mouse events dispatched through canvas handler
- TransformToolTransformer: rendered when transform tool is active
- Selection tool handlers wired for marquee-rect, marquee-ellipse,
lasso-free, lasso-poly, and magic-wand tools
- Active selection preview rect shown while dragging
- Marquee: BoxSelect (dotted rectangle) instead of Square
- Lasso: Lasso icon instead of Pen
- Transform: Maximize2 (corner arrows) instead of Move
- Gradient: Blend instead of ArrowUpRight
- Blur Brush: Droplet (water drop) instead of ScanLine
- Sharpen Brush: Triangle instead of ScanLine
- Smudge: Fingerprint instead of ScanLine
- Burn: Flame instead of Sun (was same as Dodge)
- Sponge: Droplets instead of Sun (was same as Dodge)
- Shape: Hexagon instead of Square (was same as Marquee)
- Reorder groups to match standard Photoshop toolbar layout
- Merge Crop + Eyedropper into one group
- Separate Eraser into its own group
The landing page has no dark mode support, so browser extensions like
Dark Reader force-invert colors and break the design. This adds
color-scheme: light only in both CSS and meta tags, plus a
darkreader-lock meta tag, to signal that the page should not be
auto-darkened.
The default-view redirect in HomePage fired on every mount, not just the
initial page load. A module-level flag now gates the redirect so it only
applies once per session, allowing users to switch to sidebar view when
grid is the default.
Closes#128