/* Copyright 2026 Marimo. All rights reserved. */ import { ArrowRightFromLineIcon, ArrowRightIcon, ArrowRightToLineIcon, MoreVerticalIcon, NetworkIcon, SettingsIcon, SquareFunction, WorkflowIcon, XIcon, } from "lucide-react"; import React, { memo, useId } from "react"; import { type Edge, Panel } from "reactflow"; import { getCellEditorView } from "@/core/cells/cells"; import type { CellId } from "@/core/cells/ids"; import { goToVariableDefinition } from "@/core/codemirror/go-to-definition/commands"; import type { Variable, Variables } from "@/core/variables/types"; import { ConnectionCellActionsDropdown } from "../editor/cell/cell-actions"; import { CellLink } from "../editor/links/cell-link"; import { CellLinkList } from "../editor/links/cell-link-list"; import { Button } from "../ui/button"; import { Checkbox } from "../ui/checkbox"; import { Label } from "../ui/label"; import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; import { VariableName } from "../variables/common"; import type { GraphSelection, GraphSettings, LayoutDirection } from "./types"; interface Props { view: LayoutDirection; onChange: (view: LayoutDirection) => void; settings: GraphSettings; onSettingsChange: (settings: GraphSettings) => void; } export const GraphToolbar: React.FC = memo( ({ onChange, view, settings, onSettingsChange }) => { const handleSettingChange = ( key: K, value: GraphSettings[K], ) => { onSettingsChange({ ...settings, [key]: value }); }; const markdownCheckboxId = useId(); const functionsCheckboxId = useId(); const settingsButton = (
Settings
handleSettingChange("hidePureMarkdown", Boolean(checked)) } />
handleSettingChange("hideReusableFunctions", Boolean(checked)) } />
); return (
{settingsButton}
); }, ); GraphToolbar.displayName = "GraphToolbar"; export const GraphSelectionPanel: React.FC<{ selection: GraphSelection; onClearSelection: () => void; edges: Edge[]; variables: Variables; }> = memo(({ selection, variables, onClearSelection }) => { if (!selection) { return null; } // Highlight the variable in the cell editor const highlightInCell = (cellId: CellId, variableName: string) => { const editorView = getCellEditorView(cellId); if (editorView) { goToVariableDefinition(editorView, variableName); } }; const renderSelection = () => { if (selection.type === "node") { const variablesUsed = Object.values(variables).filter((variable) => variable.usedBy.includes(selection.id), ); const variablesDeclared = Object.values(variables).filter((variable) => variable.declaredBy.includes(selection.id), ); const renderVariables = ( variables: Variable[], direction: "in" | "out", ) => ( <> {variables.length === 0 && (
--
)}
{variables.map((variable) => (
{variable.value} ({variable.dataType})
highlightInCell( direction === "in" ? variable.declaredBy[0] : variable.usedBy[0], variable.name, ) } maxCount={3} cellIds={variable.usedBy} />
))}
); return ( <>
Outputs {renderVariables(variablesDeclared, "out")}

Inputs {renderVariables(variablesUsed, "in")}
); } if (selection.type === "edge") { const edgeVariables = Object.values(variables).filter( (variable) => variable.declaredBy.includes(selection.source) && variable.usedBy.includes(selection.target), ); return ( <>
{edgeVariables.map((variable) => ( { highlightInCell(variable.declaredBy[0], variable.name); }} />
{variable.dataType}
{variable.value}
))}
); } }; return (
{renderSelection()}
); }); GraphSelectionPanel.displayName = "GraphSelectionPanel";