You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.5 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import ResizeHandles from './ResizeHandles';
import './elements.css';
const LINE_CHARS = {
single: '─',
double: '═'
};
function HorizontalLine({
element,
isSelected,
isSingleSelection,
onSelect,
onDelete,
onUpdate,
onDragStart,
onDrag,
charWidth,
charHeight,
crossroadMap = {},
toolMode
}) {
const [isDragging, setIsDragging] = useState(false);
const [dragData, setDragData] = useState(null);
const lineChar = LINE_CHARS[element.lineStyle || 'single'];
useEffect(() => {
const handleKeyPress = (e) => {
if (isSelected && e.key === 'Delete') {
onDelete();
}
};
document.addEventListener('keydown', handleKeyPress);
return () => document.removeEventListener('keydown', handleKeyPress);
}, [isSelected, onDelete]);
const handleClick = (e) => {
// Only handle selection in select mode, let other modes bubble to canvas
if (toolMode === 'select') {
e.stopPropagation();
onSelect(e);
}
};
const handleMouseDown = (e) => {
// Only handle dragging in select mode
if (toolMode !== 'select') return;
e.stopPropagation();
onSelect(e);
setIsDragging(true);
const data = onDragStart(element.id, e.clientX, e.clientY);
setDragData({ ...data, startMouseX: e.clientX, startMouseY: e.clientY });
};
const handleResize = (updates) => {
onUpdate(updates);
};
useEffect(() => {
if (!isDragging) return;
// Add class to body to disable transitions globally during drag
document.body.classList.add('dragging-active');
const handleMouseMove = (e) => {
if (dragData) {
const deltaX = e.clientX - dragData.startMouseX;
const deltaY = e.clientY - dragData.startMouseY;
onDrag(dragData, deltaX, deltaY);
}
};
const handleMouseUp = () => {
setIsDragging(false);
setDragData(null);
document.body.classList.remove('dragging-active');
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
document.body.classList.remove('dragging-active');
};
}, [isDragging, dragData, onDrag]);
// Render line with possible crossroad overrides
const renderLine = () => {
let line = '';
for (let i = 0; i < element.length; i++) {
const gridX = element.x + i;
const gridY = element.y;
const crossroadKey = `${gridX},${gridY}`;
// Use crossroad character if it exists, otherwise use line character
if (crossroadMap[crossroadKey]) {
line += crossroadMap[crossroadKey];
} else {
line += lineChar;
}
}
return line;
};
const style = {
left: `${element.x * charWidth}px`,
top: `${element.y * charHeight}px`,
width: `${element.length * charWidth}px`,
height: `${charHeight}px`
};
return (
<div
className={`line-element horizontal-line ${isSelected ? 'selected' : ''} ${isDragging ? 'dragging' : ''}`}
style={style}
onClick={handleClick}
onMouseDown={handleMouseDown}
>
{renderLine()}
{isSingleSelection && (
<ResizeHandles
element={element}
onResize={handleResize}
charWidth={charWidth}
charHeight={charHeight}
/>
)}
</div>
);
}
export default HorizontalLine;