feat: implement UI state persistence and theme toggle
Major improvements to UI state management and user preferences: - Add theme toggle with dark/light mode support - Implement Zustand persist middleware for UI state - Add ui-store for panel layout preferences (dock width, heights, tabs) - Persist tool settings (active tool, size, opacity, hardness, etc.) - Persist canvas view preferences (grid, rulers, snap-to-grid) - Persist shape tool settings - Persist collapsible section states - Fix canvas coordinate transformation for centered rendering - Constrain checkerboard and grid to canvas bounds - Add icons to all tab buttons and collapsible sections - Restructure panel-dock to use persisted state Storage impact: ~3.5KB total across all preferences Storage keys: tool-storage, canvas-view-storage, shape-storage, ui-storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -41,12 +41,15 @@ export function drawCheckerboard(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
squareSize = 10,
|
||||
color1 = '#ffffff',
|
||||
color2 = '#cccccc'
|
||||
color2 = '#cccccc',
|
||||
width?: number,
|
||||
height?: number
|
||||
): void {
|
||||
const { width, height } = ctx.canvas;
|
||||
const w = width ?? ctx.canvas.width;
|
||||
const h = height ?? ctx.canvas.height;
|
||||
|
||||
for (let y = 0; y < height; y += squareSize) {
|
||||
for (let x = 0; x < width; x += squareSize) {
|
||||
for (let y = 0; y < h; y += squareSize) {
|
||||
for (let x = 0; x < w; x += squareSize) {
|
||||
const isEven = (Math.floor(x / squareSize) + Math.floor(y / squareSize)) % 2 === 0;
|
||||
ctx.fillStyle = isEven ? color1 : color2;
|
||||
ctx.fillRect(x, y, squareSize, squareSize);
|
||||
@@ -160,26 +163,29 @@ export async function loadImageFromFile(file: File): Promise<HTMLImageElement> {
|
||||
export function drawGrid(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
gridSize: number,
|
||||
color = 'rgba(0, 0, 0, 0.1)'
|
||||
color = 'rgba(0, 0, 0, 0.1)',
|
||||
width?: number,
|
||||
height?: number
|
||||
): void {
|
||||
const { width, height } = ctx.canvas;
|
||||
const w = width ?? ctx.canvas.width;
|
||||
const h = height ?? ctx.canvas.height;
|
||||
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
// Vertical lines
|
||||
for (let x = 0; x <= width; x += gridSize) {
|
||||
for (let x = 0; x <= w; x += gridSize) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + 0.5, 0);
|
||||
ctx.lineTo(x + 0.5, height);
|
||||
ctx.lineTo(x + 0.5, h);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// Horizontal lines
|
||||
for (let y = 0; y <= height; y += gridSize) {
|
||||
for (let y = 0; y <= h; y += gridSize) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, y + 0.5);
|
||||
ctx.lineTo(width, y + 0.5);
|
||||
ctx.lineTo(w, y + 0.5);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user