import { Edge, useReactFlow } from "@xyflow/react"; import { OutputSchemaSourceKey, UINode, } from "lib/ai/workflow/workflow.interface"; import { memo, useCallback, useMemo, useRef } from "react"; import { VariableSelectContent } from "./variable-select"; import { TipTapMentionJsonContent } from "app-types/util"; import MentionInput from "../mention-input"; import { generateUUID } from "lib/utils"; import { findAvailableSchemaBySource } from "lib/ai/workflow/shared.workflow"; import { VariableMentionItem } from "./variable-mention-item"; import { useToRef } from "@/hooks/use-latest"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "ui/dropdown-menu"; interface OutputSchemaMentionInputProps { currentNodeId: string; nodes: UINode[]; edges: Edge[]; content?: TipTapMentionJsonContent; onChange: (content: TipTapMentionJsonContent) => void; placeholder?: string; editable?: boolean; className?: string; } export function OutputSchemaMentionInput({ currentNodeId, content, onChange, editable, className, }: OutputSchemaMentionInputProps) { const { getNodes, getEdges } = useReactFlow(); const latestContent = useToRef(content!); const handleChange = useCallback( ({ json }: { json: TipTapMentionJsonContent }) => { onChange(json); }, [], ); const onRemove = useCallback((id: string) => { const newContent = structuredClone(latestContent.current); newContent.content.some((item) => { if (item?.content?.length) { const targetIndex = item.content.findIndex( (item) => item.type == "mention" && item.attrs.id === id, ); if (targetIndex !== -1) { item.content.splice(targetIndex, 1); return true; } return false; } }); onChange(newContent); }, []); const MentionItem = useCallback( ({ id, label }: { id: string; label: string }) => { const item = JSON.parse(label) as OutputSchemaSourceKey; const nodes = getNodes(); const edges = getEdges(); const labelData = findAvailableSchemaBySource({ nodeId: currentNodeId, source: item, nodes: nodes.map((node) => node.data), edges, }); const handleRemove = () => onRemove(id); return ( ); }, [], ); const Suggestion = useMemo( () => outputSchemaMentionInputSuggestionBuilder(currentNodeId), [currentNodeId], ); return ( ); } const outputSchemaMentionInputSuggestionBuilder = ( nodeId: string, ): React.FC<{ onClose: () => void; onSelectMention: (item: { label: string; id: string }) => void; top: number; left: number; }> => memo(function OutputSchemaMentionInputSuggestion({ onSelectMention, top, left, onClose, }) { const mentionRef = useRef(null); return (
{ onSelectMention({ id: generateUUID(), label: JSON.stringify({ nodeId: item.nodeId, path: item.path, }), }); }} />
); });