Initial Commit 🚀 🚀

This commit is contained in:
Abhishek Kumar 2025-09-09 14:37:32 +05:30
commit 4f2a629340
444 changed files with 76863 additions and 0 deletions

View file

@ -0,0 +1,44 @@
import { Position } from "@xyflow/react";
import { ReactNode } from "react";
import { BaseHandle } from "@/components/flow/nodes/BaseHandle";
import { BaseNode } from "@/components/flow/nodes/BaseNode";
import { NodeHeader, NodeHeaderIcon, NodeHeaderTitle } from "@/components/flow/nodes/NodeHeader";
interface NodeContentProps {
selected: boolean;
invalid?: boolean;
title: string;
icon: ReactNode;
bgColor: string;
hasSourceHandle?: boolean;
hasTargetHandle?: boolean;
children?: ReactNode;
className?: string;
}
export const NodeContent = ({
selected,
invalid,
title,
icon,
bgColor,
hasSourceHandle = false,
hasTargetHandle = false,
children,
className = "",
}: NodeContentProps) => {
return (
<BaseNode selected={selected} invalid={invalid} className={`p-0 overflow-hidden ${className}`}>
{hasTargetHandle && <BaseHandle type="target" position={Position.Top} />}
<NodeHeader className={`px-3 py-2 border-b ${bgColor}`}>
<NodeHeaderIcon>{icon}</NodeHeaderIcon>
<NodeHeaderTitle>{title}</NodeHeaderTitle>
</NodeHeader>
<div className="p-3">
{children}
</div>
{hasSourceHandle && <BaseHandle type="source" position={Position.Bottom} />}
</BaseNode>
);
};

View file

@ -0,0 +1,63 @@
import { AlertCircle } from "lucide-react";
import { ReactNode } from "react";
import { FlowNodeData } from "@/components/flow/types";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
interface NodeEditDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
nodeData: FlowNodeData;
title: string;
children: ReactNode;
onSave?: () => void;
}
export const NodeEditDialog = ({
open,
onOpenChange,
nodeData,
title,
children,
onSave
}: NodeEditDialogProps) => {
const handleClose = () => onOpenChange(false);
const handleSave = () => {
if (onSave) {
onSave();
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
className="max-h-[85vh] overflow-y-auto"
style={{ maxWidth: "1200px", width: "95vw" }}
>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
Configure the settings for this node in your workflow.
</DialogDescription>
{nodeData.invalid && nodeData.validationMessage && (
<div className="mt-2 flex items-center gap-2 rounded-md bg-red-50 p-2 text-sm text-red-500 border border-red-200">
<AlertCircle className="h-4 w-4" />
<span>{nodeData.validationMessage}</span>
</div>
)}
</DialogHeader>
<div className="grid gap-4 py-4">
{children}
</div>
<DialogFooter>
<div className="flex items-center gap-2">
<Button variant="outline" onClick={handleClose}>Cancel</Button>
<Button onClick={handleSave}>Save</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

View file

@ -0,0 +1,39 @@
import { useReactFlow } from "@xyflow/react";
import { useCallback, useState } from "react";
import { FlowEdge, FlowNode, FlowNodeData } from "@/components/flow/types";
interface UseNodeHandlersProps {
id: string;
additionalData?: Record<string, string | boolean>;
}
export const useNodeHandlers = ({ id, additionalData = {} }: UseNodeHandlersProps) => {
const [open, setOpen] = useState(false);
const { setNodes } = useReactFlow<FlowNode, FlowEdge>();
const handleSaveNodeData = useCallback(
(updatedData: FlowNodeData) => {
setNodes((nodes) => {
const updatedNodes = nodes.map((node) =>
node.id === id
? { ...node, data: { ...node.data, ...updatedData, ...additionalData } }
: node
);
return updatedNodes;
});
},
[id, setNodes, additionalData]
);
const handleDeleteNode = useCallback(() => {
setNodes((nodes) => nodes.filter((node) => node.id !== id));
}, [id, setNodes]);
return {
open,
setOpen,
handleSaveNodeData,
handleDeleteNode,
};
};