Files
paint-ui/lib/tool-loader.ts
Sebastian Krüger 8f595ac6c4 feat(phase-13): implement gradient tool with linear, radial, and angular modes
Add comprehensive gradient tool with three gradient types and full UI integration.

Features:
- Gradient tool with drag-to-create interaction
- Three gradient types: Linear, Radial, and Angular (conic)
- Live preview during drag with 70% opacity overlay
- Primary and secondary color selection
- Gradient type selector in tool options
- Undo/redo support through command system
- Fallback to radial gradient for browsers without conic gradient support

Changes:
- Created tools/gradient-tool.ts with GradientTool class
- Added 'gradient' to ToolType in types/tool.ts
- Extended ToolSettings with secondaryColor and gradientType
- Updated store/tool-store.ts with setSecondaryColor and setGradientType methods
- Added gradient tool loading in lib/tool-loader.ts
- Added gradient button to tool palette with 'G' shortcut
- Added gradient tool options UI in components/editor/tool-options.tsx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 19:48:00 +01:00

175 lines
4.7 KiB
TypeScript

import type { BaseTool } from '@/tools';
import type { ToolType } from '@/types';
/**
* Tool loader cache
*/
const toolCache = new Map<string, BaseTool>();
const toolLoadingPromises = new Map<string, Promise<BaseTool>>();
/**
* Dynamically import and instantiate a tool
* Supports both ToolType and internal tool keys (like 'rectangular-select')
*/
async function loadTool(toolKey: string): Promise<BaseTool> {
// Check cache first
if (toolCache.has(toolKey)) {
return toolCache.get(toolKey)!;
}
// Check if already loading
if (toolLoadingPromises.has(toolKey)) {
return toolLoadingPromises.get(toolKey)!;
}
// Start loading
const loadPromise = (async () => {
let tool: BaseTool;
switch (toolKey) {
case 'pencil': {
const { PencilTool } = await import('@/tools/pencil-tool');
tool = new PencilTool();
break;
}
case 'brush': {
const { BrushTool } = await import('@/tools/brush-tool');
tool = new BrushTool();
break;
}
case 'eraser': {
const { EraserTool } = await import('@/tools/eraser-tool');
tool = new EraserTool();
break;
}
case 'fill': {
const { FillTool } = await import('@/tools/fill-tool');
tool = new FillTool();
break;
}
case 'gradient': {
const { GradientTool } = await import('@/tools/gradient-tool');
tool = new GradientTool();
break;
}
case 'eyedropper': {
const { EyedropperTool } = await import('@/tools/eyedropper-tool');
tool = new EyedropperTool();
break;
}
case 'select':
case 'rectangular-select': {
const { RectangularSelectionTool } = await import('@/tools/rectangular-selection-tool');
tool = new RectangularSelectionTool();
break;
}
case 'elliptical-select': {
const { EllipticalSelectionTool } = await import('@/tools/elliptical-selection-tool');
tool = new EllipticalSelectionTool();
break;
}
case 'lasso-select': {
const { LassoSelectionTool } = await import('@/tools/lasso-selection-tool');
tool = new LassoSelectionTool();
break;
}
case 'magic-wand': {
const { MagicWandTool } = await import('@/tools/magic-wand-tool');
tool = new MagicWandTool();
break;
}
case 'move': {
const { MoveTool } = await import('@/tools/move-tool');
tool = new MoveTool();
break;
}
case 'transform': {
const { FreeTransformTool } = await import('@/tools/free-transform-tool');
tool = new FreeTransformTool();
break;
}
case 'shape': {
const { ShapeTool } = await import('@/tools/shape-tool');
tool = new ShapeTool();
break;
}
case 'text': {
const { TextTool } = await import('@/tools/text-tool');
tool = new TextTool();
break;
}
case 'clone': {
const { CloneStampTool } = await import('@/tools/clone-stamp-tool');
tool = new CloneStampTool();
break;
}
case 'smudge': {
const { SmudgeTool } = await import('@/tools/smudge-tool');
tool = new SmudgeTool();
break;
}
case 'dodge': {
const { DodgeBurnTool } = await import('@/tools/dodge-burn-tool');
tool = new DodgeBurnTool();
break;
}
default: {
// Fallback to pencil tool
const { PencilTool } = await import('@/tools/pencil-tool');
tool = new PencilTool();
}
}
// Cache the tool
toolCache.set(toolKey, tool);
toolLoadingPromises.delete(toolKey);
return tool;
})();
toolLoadingPromises.set(toolKey, loadPromise);
return loadPromise;
}
/**
* Get a tool instance (loads it if not cached)
* Accepts both ToolType and internal tool keys (e.g., 'rectangular-select')
*/
export async function getTool(toolKey: ToolType | string): Promise<BaseTool> {
return loadTool(toolKey);
}
/**
* Preload a tool (for performance optimization)
*/
export function preloadTool(toolKey: ToolType | string): void {
loadTool(toolKey).catch((error) => {
console.error(`Failed to preload tool ${toolKey}:`, error);
});
}
/**
* Preload commonly used tools
*/
export function preloadCommonTools(): void {
// Preload the most commonly used tools
preloadTool('pencil');
preloadTool('brush');
preloadTool('eraser');
}
/**
* Check if a tool is loaded
*/
export function isToolLoaded(toolKey: ToolType | string): boolean {
return toolCache.has(toolKey);
}
/**
* Clear tool cache (for testing)
*/
export function clearToolCache(): void {
toolCache.clear();
toolLoadingPromises.clear();
}