Files
patchy631--ai-engineering-hub/open-agent-builder/components/app/(home)/sections/workflow-builder/EdgeLabelModal.tsx
T
2026-07-13 12:37:47 +08:00

158 lines
6.2 KiB
TypeScript

"use client";
import { motion, AnimatePresence } from "framer-motion";
import { useState } from "react";
import type { Edge } from "@xyflow/react";
interface EdgeLabelModalProps {
edge: Edge | null;
isOpen: boolean;
onClose: () => void;
onSave: (edgeId: string, label: string) => void;
}
export default function EdgeLabelModal({ edge, isOpen, onClose, onSave }: EdgeLabelModalProps) {
const [label, setLabel] = useState(edge?.label as string || '');
const [labelType, setLabelType] = useState<'custom' | 'true' | 'false' | 'none'>(
edge?.label === 'true' ? 'true' :
edge?.label === 'false' ? 'false' :
edge?.label ? 'custom' : 'none'
);
const handleSave = () => {
if (!edge) return;
let finalLabel = '';
if (labelType === 'true') finalLabel = 'true';
else if (labelType === 'false') finalLabel = 'false';
else if (labelType === 'custom') finalLabel = label;
onSave(edge.id, finalLabel);
onClose();
};
if (!edge) return null;
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black-alpha-48 z-[200] flex items-center justify-center p-20"
onClick={onClose}
>
<motion.div
initial={{ scale: 0.95, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.95, opacity: 0 }}
transition={{ duration: 0.2 }}
onClick={(e) => e.stopPropagation()}
className="bg-accent-white rounded-16 shadow-2xl max-w-400 w-full"
>
{/* Header */}
<div className="p-20 border-b border-border-faint">
<h2 className="text-title-h4 text-accent-black">Edit Connection</h2>
<p className="text-body-small text-black-alpha-48 mt-4">
Add a label to this connection
</p>
</div>
{/* Content */}
<div className="p-20 space-y-16">
{/* Label Type */}
<div>
<label className="block text-label-small text-black-alpha-48 mb-8">
Label Type
</label>
<div className="space-y-8">
<button
onClick={() => setLabelType('none')}
className={`w-full p-12 rounded-8 border-2 transition-all text-left ${
labelType === 'none'
? 'border-heat-100 bg-heat-4'
: 'border-border-faint bg-background-base hover:border-border-light'
}`}
>
<p className="text-body-small text-accent-black font-medium">No Label</p>
<p className="text-body-small text-black-alpha-48 mt-4">Standard connection</p>
</button>
<button
onClick={() => setLabelType('true')}
className={`w-full p-12 rounded-8 border-2 transition-all text-left ${
labelType === 'true'
? 'border-heat-100 bg-heat-4'
: 'border-border-faint bg-background-base hover:border-border-light'
}`}
>
<p className="text-body-small text-accent-black font-medium">True Branch</p>
<p className="text-body-small text-black-alpha-48 mt-4">For If/Else true condition</p>
</button>
<button
onClick={() => setLabelType('false')}
className={`w-full p-12 rounded-8 border-2 transition-all text-left ${
labelType === 'false'
? 'border-heat-100 bg-heat-4'
: 'border-border-faint bg-background-base hover:border-border-light'
}`}
>
<p className="text-body-small text-accent-black font-medium">False Branch</p>
<p className="text-body-small text-black-alpha-48 mt-4">For If/Else false condition</p>
</button>
<button
onClick={() => setLabelType('custom')}
className={`w-full p-12 rounded-8 border-2 transition-all text-left ${
labelType === 'custom'
? 'border-heat-100 bg-heat-4'
: 'border-border-faint bg-background-base hover:border-border-light'
}`}
>
<p className="text-body-small text-accent-black font-medium">Custom Label</p>
<p className="text-body-small text-black-alpha-48 mt-4">Your own text</p>
</button>
</div>
</div>
{/* Custom Label Input */}
{labelType === 'custom' && (
<div>
<label className="block text-label-small text-black-alpha-48 mb-8">
Label Text
</label>
<input
type="text"
value={label}
onChange={(e) => setLabel(e.target.value)}
placeholder="Enter label text"
className="w-full px-12 py-8 bg-background-base border border-border-faint rounded-8 text-body-medium text-accent-black focus:outline-none focus:border-heat-100 transition-colors"
/>
</div>
)}
</div>
{/* Footer */}
<div className="p-20 border-t border-border-faint flex items-center justify-end gap-12">
<button
onClick={onClose}
className="px-20 py-10 text-body-medium text-black-alpha-48 hover:text-accent-black transition-colors"
>
Cancel
</button>
<button
onClick={handleSave}
className="px-24 py-10 bg-heat-100 hover:bg-heat-200 text-white rounded-8 transition-all active:scale-[0.98] text-body-medium font-medium"
>
Save
</button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
);
}