import { ArrowDown, ArrowUp, ChevronDown, ChevronRight, GitBranch, Pencil } from "lucide-react"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import type { MobileWorkflowNodeSummary, WorkflowNodeReorderDirection } from "./workflow-mobile-graph"; import "./MobileWorkflowGraphView.css"; interface MobileWorkflowGraphViewProps { rows: MobileWorkflowNodeSummary[]; selectedNodeId?: string | null; selectedEdgeId?: string | null; onSelectNode: (id: string) => void; onSelectEdge: (id: string) => void; onCreateConnection?: (source: string, target: string) => void; canReorder?: boolean; onMoveNode?: (id: string, direction: WorkflowNodeReorderDirection) => void; } function reorderAvailability(rows: MobileWorkflowNodeSummary[], index: number) { const row = rows[index]; if (!row?.editable) return { up: false, down: false }; return { up: rows[index - 1]?.editable === true, down: rows[index + 1]?.editable === true, }; } function NodeRow({ row, depth, selectedNodeId, selectedEdgeId, onSelectNode, onSelectEdge, onCreateConnection, canReorder, onMoveNode, canMoveUp, canMoveDown, }: { row: MobileWorkflowNodeSummary; depth: number; selectedNodeId?: string | null; selectedEdgeId?: string | null; onSelectNode: (id: string) => void; onSelectEdge: (id: string) => void; onCreateConnection?: (source: string, target: string) => void; canReorder?: boolean; onMoveNode?: (id: string, direction: WorkflowNodeReorderDirection) => void; canMoveUp: boolean; canMoveDown: boolean; }) { const { t } = useTranslation("app"); const hasChildren = row.children.length > 0; const [expanded, setExpanded] = useState(depth === 0); const [connectPickerOpen, setConnectPickerOpen] = useState(false); const selected = selectedNodeId === row.id; const connectionTargets = row.connectionTargets ?? []; const canCreateConnection = !!onCreateConnection && row.editable && connectionTargets.length > 0; const showReorderControls = !!canReorder && !!onMoveNode && row.editable; return (
{hasChildren || showReorderControls ? (
{showReorderControls ? ( <> ) : null} {hasChildren ? ( ) : null}
) : null}
{canCreateConnection ? (
) : null} {/* FNXC:WorkflowEditor 2026-06-16-23:45: Mobile and compact simple editing do not render the React Flow canvas, so drag-to-connect handles are unavailable. This picker gives touch users a non-canvas path while the editor still owns edge validation and construction. */} {canCreateConnection && connectPickerOpen ? (
) : null} {(row.columnName || row.outgoing.length > 0) && (
{row.columnName ? {row.columnName} : null} {row.outgoing.map((edge) => ( ))}
)} {hasChildren && expanded ? (
{row.children.map((child, index) => { const move = reorderAvailability(row.children, index); return ( ); })}
) : null}
); } export function MobileWorkflowGraphView({ rows, selectedNodeId, selectedEdgeId, onSelectNode, onSelectEdge, onCreateConnection, canReorder, onMoveNode, }: MobileWorkflowGraphViewProps) { const { t } = useTranslation("app"); if (rows.length === 0) { return (
{t("workflowNodes.mobileGraphEmpty", "No graph nodes yet.")}
); } return (
{rows.map((row, index) => { const move = reorderAvailability(rows, index); return ( ); })}
); }