Files
lemonspace_app/components/canvas/canvas-node-template-picker.tsx
Matthias Meister fa6a41f775 feat(canvas): implement edge insertion reflow and enhance connection validation
- Introduced a new CSS transition for edge insertion reflowing to improve visual feedback during node adjustments.
- Enhanced the connection validation logic to include options for optimistic edges, ensuring better handling of edge creation scenarios.
- Updated the canvas connection drop menu to support additional templates and improved edge insertion handling.
- Refactored edge insertion logic to accommodate local node position adjustments during reflow operations.
- Added tests for new edge insertion features and connection validation improvements.
2026-04-05 23:25:26 +02:00

94 lines
2.3 KiB
TypeScript

"use client";
import {
FolderOpen,
Frame,
Focus,
GitCompare,
ImageDown,
Image,
Package,
Palette,
Sparkles,
StickyNote,
Sun,
Type,
Video,
type LucideIcon,
} from "lucide-react";
import { CommandGroup, CommandItem } from "@/components/ui/command";
import {
CANVAS_NODE_TEMPLATES,
type CanvasNodeTemplate,
} from "@/lib/canvas-node-templates";
const NODE_ICONS: Record<CanvasNodeTemplate["type"], LucideIcon> = {
image: Image,
text: Type,
prompt: Sparkles,
note: StickyNote,
frame: Frame,
compare: GitCompare,
group: FolderOpen,
asset: Package,
video: Video,
curves: Sparkles,
"color-adjust": Palette,
"light-adjust": Sun,
"detail-adjust": Focus,
render: ImageDown,
};
const NODE_SEARCH_KEYWORDS: Partial<
Record<CanvasNodeTemplate["type"], string[]>
> = {
image: ["image", "photo", "foto"],
text: ["text", "typo"],
prompt: ["prompt", "ai", "generate", "ki-bild", "ki", "bild"],
note: ["note", "sticky", "notiz"],
frame: ["frame", "artboard"],
compare: ["compare", "before", "after", "vergleich"],
group: ["group", "gruppe", "folder"],
asset: ["asset", "freepik", "stock"],
video: ["video", "pexels", "clip"],
curves: ["curves", "tone", "contrast"],
"color-adjust": ["color", "hue", "saturation"],
"light-adjust": ["light", "exposure", "brightness"],
"detail-adjust": ["detail", "sharp", "grain"],
render: ["render", "export", "download"],
};
export type CanvasNodeTemplatePickerProps = {
onPick: (template: CanvasNodeTemplate) => void;
groupHeading?: string;
templates?: readonly CanvasNodeTemplate[];
};
/**
* Knoten-Template-Liste für cmdk. Eltern: `<Command><CommandInput/><CommandList><CommandEmpty/> <CanvasNodeTemplatePicker /> …`.
*/
export function CanvasNodeTemplatePicker({
onPick,
groupHeading = "Knoten",
templates = CANVAS_NODE_TEMPLATES,
}: CanvasNodeTemplatePickerProps) {
return (
<CommandGroup heading={groupHeading}>
{templates.map((template) => {
const Icon = NODE_ICONS[template.type];
return (
<CommandItem
key={template.type}
keywords={NODE_SEARCH_KEYWORDS[template.type] ?? []}
onSelect={() => onPick(template)}
>
<Icon className="size-4" />
{template.label}
</CommandItem>
);
})}
</CommandGroup>
);
}