import type { ComponentProps, ReactNode } from "react"; import { NodeResizer } from "@xyflow/react"; import { useContext } from "react"; import FlowContext from "@/lib/graph/flowContext"; import { useConnectionPathRole } from "@/lib/graph/flowContext"; import { cn } from "@/lib/utils"; /** Default min size for resizable nodes (used by NodeResizer). */ export const RESIZE_MIN_WIDTH = 120; export const RESIZE_MIN_HEIGHT = 80; export type BaseNodeProps = ComponentProps<"div"> & { /** When true, shows resize handles on corners/edges (via NodeResizer). Requires nodeId when used inside React Flow. */ resizable?: boolean; /** Node id for the resize control (required when resizable is true). */ nodeId?: string; /** Connection handles (InputHandle, OutputHandle). Rendered outside the overflow layer so they stay visible. */ handles?: ReactNode; /** When provided, node uses this size (e.g. from React Flow width/height). Enables correct resize behavior. */ dimensions?: { width: number; height: number }; /** When true, node is selected (from React Flow NodeProps). Used for visible selected state. */ selected?: boolean; /** Optional min/max for NodeResizer. Omit to use RESIZE_MIN_WIDTH / RESIZE_MIN_HEIGHT. */ resizeConstraints?: { minWidth?: number; minHeight?: number; maxWidth?: number; maxHeight?: number }; }; export function BaseNode({ className, style, dimensions, resizable, nodeId, handles, children, selected, resizeConstraints, ...props }: BaseNodeProps) { const flowContext = useContext(FlowContext); const isFullscreenInstance = Boolean(nodeId && flowContext?.fullscreenNodeId === nodeId); const connectionPathRole = useConnectionPathRole(nodeId); const hasSize = dimensions && dimensions.width > 0 && dimensions.height > 0; // Don't set overflow: hidden on the root — handles are positioned at left/right -10px // and would be clipped. The inner content wrapper has overflow-hidden for scrolling. const appliedStyle = hasSize ? { ...style, width: dimensions.width, height: dimensions.height, display: "flex" as const, flexDirection: "column" as const, contain: "layout" as const, } : style ? { ...style, display: "flex", flexDirection: "column" as const } : undefined; const minW = resizeConstraints?.minWidth ?? RESIZE_MIN_WIDTH; const minH = resizeConstraints?.minHeight ?? RESIZE_MIN_HEIGHT; return (