import type { ReactNode } from "react"; import { Brush, Camera, Copy, FileText, Grid2x2, Lock, LockOpen, Maximize2, PencilLine, Crop, SlidersHorizontal, Smile, Upload, Scaling } from "lucide-react"; import type { CanvasNodeData } from "@/types/canvas"; import type { NodeToolbarGroup } from "@/lib/canvas/tool-registry"; type ImageNodeActionToolId = "copyPrompt" | "reversePrompt" | "replace" | "resize" | "annotation" | "maskEdit" | "emotion" | "portraitTexture" | "crop" | "split" | "upscale" | "superResolve" | "angle" | "view"; type ImageToolHandlers = { onUpload: (node: CanvasNodeData) => void; onToggleFreeResize: (node: CanvasNodeData) => void; onAnnotate: (node: CanvasNodeData) => void; onMaskEdit: (node: CanvasNodeData) => void; onEmotion: (node: CanvasNodeData) => void; onPortraitTexture: (node: CanvasNodeData) => void; onCrop: (node: CanvasNodeData) => void; onSplit: (node: CanvasNodeData) => void; onUpscale: (node: CanvasNodeData) => void; onSuperResolve: (node: CanvasNodeData) => void; onAngle: (node: CanvasNodeData) => void; onViewImage: (node: CanvasNodeData) => void; onCopyPrompt: (node: CanvasNodeData) => void; onReversePrompt: (node: CanvasNodeData) => void; }; type ImageToolDefinition = { id: ImageNodeActionToolId; label: string | ((node: CanvasNodeData) => string); icon: (node: CanvasNodeData) => ReactNode; group: NodeToolbarGroup; order: number; section?: string; description?: string; active?: (node: CanvasNodeData) => boolean; run: (node: CanvasNodeData, handlers: ImageToolHandlers) => void; }; const imageToolDefinitions: ImageToolDefinition[] = [ { id: "copyPrompt", section: "生成信息", label: "复制提示词", icon: () => , group: "more", order: 50, run: (node, handlers) => handlers.onCopyPrompt(node), }, { id: "reversePrompt", section: "生成信息", label: "反推提示词", icon: () => , group: "more", order: 60, run: (node, handlers) => handlers.onReversePrompt(node), }, { id: "replace", label: "替换图片", icon: () => , group: "more", section: "素材", order: 45, run: (node, handlers) => handlers.onUpload(node), }, { id: "resize", label: "锁定宽高比", section: "节点管理", active: (node) => !node.metadata?.freeResize, icon: (node) => (node.metadata?.freeResize ? : ), group: "more", order: 70, run: (node, handlers) => handlers.onToggleFreeResize(node), }, { id: "annotation", section: "拆分与标记", description: "添加标记,另存为新图片", label: "标注", icon: () => , group: "process", order: 40, run: (node, handlers) => handlers.onAnnotate(node), }, { id: "maskEdit", label: "局部重绘", description: "涂抹要修改的区域,生成新图片", icon: () => , group: "primary", order: 10, run: (node, handlers) => handlers.onMaskEdit(node), }, { id: "emotion", label: "表情调整", section: "人像调整", description: "调整人物表情,生成新图片", icon: () => , group: "portrait", order: 50, run: (node, handlers) => handlers.onEmotion(node), }, { id: "portraitTexture", label: "质感调整", section: "人像调整", description: "设置肤质、光影与融合,再执行生成", icon: () => , group: "portrait", order: 60, run: (node, handlers) => handlers.onPortraitTexture(node), }, { id: "crop", label: "裁剪", section: "构图与尺寸", description: "保留所选区域,生成新图片", icon: () => , group: "process", order: 10, run: (node, handlers) => handlers.onCrop(node), }, { id: "split", label: "宫格切分", section: "拆分与标记", description: "按行列拆成多个图片节点", icon: () => , group: "process", order: 30, run: (node, handlers) => handlers.onSplit(node), }, { id: "upscale", label: "调整尺寸", section: "构图与尺寸", description: "插值放大像素尺寸,不是 AI 超分", icon: () => , group: "process", order: 20, run: (node, handlers) => handlers.onUpscale(node), }, { id: "angle", label: "多角度", section: "视角", description: "调整摄影机角度,生成新视角", icon: () => , group: "viewpoint", order: 20, run: (node, handlers) => handlers.onAngle(node), }, { id: "view", label: "预览", icon: () => , group: "utility", order: 10, run: (node, handlers) => handlers.onViewImage(node), }, ]; export function buildImageToolbarTools(node: CanvasNodeData, handlers: ImageToolHandlers) { return imageToolDefinitions.map((tool) => ({ id: tool.id, label: resolveToolText(tool.label, node), icon: tool.icon(node), group: tool.group, order: tool.order, section: tool.section, description: tool.description, active: tool.active?.(node), onClick: () => tool.run(node, handlers), })); } function resolveToolText(value: string | ((node: CanvasNodeData) => string), node: CanvasNodeData) { return typeof value === "function" ? value(node) : value; }