Interactive Diagram Editor in React
This challenge requires you to build a foundational interactive diagram editor using React and TypeScript. A diagram editor allows users to visually represent relationships and elements, which is crucial for applications like flowcharts, mind maps, system architecture diagrams, and more. Your task is to implement core functionalities for creating, manipulating, and connecting visual elements.
Problem Description
You will create a React component that functions as a basic diagram editor. The editor should allow users to:
- Add Shapes: Users should be able to add different types of shapes (e.g., rectangles, circles) to the canvas.
- Select and Move Shapes: Users should be able to click on a shape to select it and then drag it to a new position on the canvas.
- Draw Connections: Users should be able to draw connecting lines between shapes. These connections should ideally "stick" to the shapes they are connected to, so they move with the shapes.
- Delete Shapes and Connections: Users should be able to select and delete shapes or connections.
Key Requirements:
- React Components: The editor should be built using functional React components and TypeScript.
- State Management: Manage the state of shapes, their positions, and connections effectively. Consider how to handle updates and rendering.
- User Interaction: Implement event handling for mouse clicks, drags, and potentially keyboard events for deletion.
- Visual Representation: Use basic SVG elements or HTML elements for rendering shapes and connections. SVG is generally preferred for this type of application.
- Connection Logic: Implement logic to draw lines between selected points on shapes.
Expected Behavior:
- When the user clicks on an empty area of the canvas, nothing should happen (or a new shape could be added, depending on future extensions).
- Clicking on a shape should highlight it (e.g., with a border).
- Dragging a selected shape should visually update its position on the canvas.
- Clicking on a shape and then clicking on another shape should create a visual connection between them.
- Deleting a selected shape or connection should remove it from the canvas.
Edge Cases:
- What happens if a user tries to connect a shape to itself?
- How should connections be handled if shapes are deleted?
- What if shapes overlap significantly?
Examples
Example 1: Adding and Moving Shapes
- Input State: An empty canvas.
- User Action:
- Clicks a "Add Rectangle" button.
- Clicks on the canvas at coordinates (100, 50). A rectangle appears.
- Clicks on the rectangle to select it. A border appears.
- Drags the rectangle to coordinates (200, 150).
- Output State: A single rectangle is now positioned at (200, 150) with a selection border.
Example 2: Drawing and Deleting Connections
- Input State: Two rectangles,
RectAat (50, 50) andRectBat (250, 50). - User Action:
- Selects
RectA. - Clicks on
RectB. - A line is drawn connecting
RectAandRectB. - Selects the line.
- Presses the "Delete" key.
- Selects
- Output State: The line connecting
RectAandRectBis removed.RectAandRectBremain.
Example 3: Connection Persistence with Shape Movement
- Input State:
RectAat (50, 50) andRectBat (250, 50), connected by a line. - User Action:
- Selects
RectA. - Drags
RectAto (150, 100).
- Selects
- Output State:
RectAis now at (150, 100). The line connectingRectAandRectBhas updated its starting point to (150, 100) while the ending point remains connected toRectBat (250, 50).
Constraints
- The editor should be able to render at least 100 shapes and 500 connections without significant performance degradation (aim for smooth drag operations).
- Shape positions will be represented by
xandycoordinates (integers or floats). - Shapes will have a fixed width and height for simplicity in this initial challenge.
- Connections should be simple straight lines for this challenge.
Notes
- Consider using a state management library (like
useStatewith reducers, oruseReducer) to manage the complex state of shapes and connections. - SVG is highly recommended for rendering graphics. You'll likely use
<rect>,<circle>, and<line>elements. - For drawing connections, you might need to calculate connection points on the shapes (e.g., center points, or edges).
- Think about how to uniquely identify each shape and connection for selection and deletion.
- The "sticking" behavior of connections can be implemented by recalculating the line's endpoints whenever a connected shape moves.
- Focus on the core functionality first. Visual styling and advanced features (like different shape types, curved lines, text labels, grouping) can be considered for future extensions.