147 lines
5.7 KiB
TypeScript
147 lines
5.7 KiB
TypeScript
import { useRef, type RefObject } from "react";
|
|
import { Block } from "../../../../types/exportedTypes";
|
|
import ElementComponent from "../element/ElementComponent";
|
|
import { ResizeIcon } from "../../../icons/ExportToolsIcons";
|
|
import ElementDropdown from "../element/ElementDropdown";
|
|
|
|
interface BlockComponentProps {
|
|
block: Block;
|
|
handleAddElement: (blockId: string, type: UIType, graphType?: GraphTypes) => void;
|
|
editMode: boolean;
|
|
selectedBlock: string | null;
|
|
selectedElement: string | null;
|
|
calculateMinBlockSize: (block: Block) => { width: number; height: number };
|
|
handleBlockClick: (blockId: string, event: React.MouseEvent) => void;
|
|
handleElementClick: (blockId: string, elementId: string, event: React.MouseEvent) => void;
|
|
handleElementDragStart: (elementId: string, event: React.MouseEvent) => void;
|
|
handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void;
|
|
handleBlockResizeStart: (blockId: string, event: React.MouseEvent) => void;
|
|
setShowElementDropdown: (blockId: string | null) => void;
|
|
showElementDropdown: string | null;
|
|
blockRef: RefObject<HTMLDivElement>;
|
|
handleBlockDragStart: (blockId: string, event: React.MouseEvent) => void;
|
|
}
|
|
|
|
const BlockComponent: React.FC<BlockComponentProps> = ({
|
|
block,
|
|
handleAddElement,
|
|
editMode,
|
|
selectedBlock,
|
|
selectedElement,
|
|
calculateMinBlockSize,
|
|
handleBlockClick,
|
|
handleElementClick,
|
|
handleElementDragStart,
|
|
handleElementResizeStart,
|
|
handleBlockResizeStart,
|
|
setShowElementDropdown,
|
|
showElementDropdown,
|
|
blockRef,
|
|
handleBlockDragStart,
|
|
}) => {
|
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
|
|
const minSize = calculateMinBlockSize(block);
|
|
const isSelected = selectedBlock === block.blockUuid;
|
|
const isDraggable = editMode && (block.positionType === "absolute" || block.positionType === "fixed");
|
|
|
|
const handleMouseDown = (event: React.MouseEvent) => {
|
|
if (isDraggable) {
|
|
handleBlockDragStart(block.blockUuid, event);
|
|
}
|
|
handleBlockClick(block.blockUuid, event);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
key={block.blockUuid}
|
|
data-block-id={block.blockUuid}
|
|
ref={isSelected ? blockRef : null}
|
|
className={`block ${isSelected ? "selected" : ""} ${editMode ? "edit-mode" : ""} ${isDraggable ? "draggable" : ""}`}
|
|
style={{
|
|
...block.style,
|
|
position: block.positionType || "relative",
|
|
left: block.positionType === "absolute" || block.positionType === "fixed" ? `${block.position?.x || 0}px` : "auto",
|
|
top: block.positionType === "absolute" || block.positionType === "fixed" ? `${block.position?.y || 0}px` : "auto",
|
|
width: block.size?.width || 400,
|
|
height: block.size?.height || 300,
|
|
minWidth: minSize.width,
|
|
minHeight: minSize.height,
|
|
zIndex: block.zIndex || 1,
|
|
cursor: isDraggable ? "move" : "pointer",
|
|
}}
|
|
onClick={handleMouseDown}
|
|
>
|
|
{/* Add Element Button */}
|
|
{editMode && isSelected && (
|
|
<div className="element-container">
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowElementDropdown(showElementDropdown === block.blockUuid ? null : block.blockUuid);
|
|
}}
|
|
className="add-element-button"
|
|
>
|
|
+ Add Element
|
|
</button>
|
|
|
|
<ElementDropdown
|
|
showElementDropdown={showElementDropdown}
|
|
handleAddElement={(blockId, type, graphType) => handleAddElement(blockId, type as UIType, graphType as GraphTypes)}
|
|
dropdownRef={dropdownRef}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* Elements */}
|
|
{block.elements.map((el) => (
|
|
<ElementComponent
|
|
key={el.elementUuid}
|
|
element={el}
|
|
blockId={block.blockUuid}
|
|
editMode={editMode}
|
|
selectedElement={selectedElement}
|
|
handleElementClick={handleElementClick}
|
|
handleElementDragStart={handleElementDragStart}
|
|
handleElementResizeStart={handleElementResizeStart}
|
|
/>
|
|
))}
|
|
|
|
{/* Block resize handle */}
|
|
{editMode && isSelected && (
|
|
<div className="resize-handle" onMouseDown={(e) => handleBlockResizeStart(block.blockUuid, e)}>
|
|
<ResizeIcon />
|
|
</div>
|
|
)}
|
|
|
|
{/* Drag handle indicator for absolute/fixed blocks */}
|
|
{isDraggable && editMode && (
|
|
<div
|
|
className="drag-handle"
|
|
style={{
|
|
position: "absolute",
|
|
top: "5px",
|
|
left: "5px",
|
|
width: "20px",
|
|
height: "20px",
|
|
backgroundColor: "rgba(33, 150, 243, 0.8)",
|
|
borderRadius: "4px",
|
|
cursor: "move",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
color: "white",
|
|
fontSize: "12px",
|
|
zIndex: 10,
|
|
}}
|
|
title="Drag to move"
|
|
>
|
|
⤣
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default BlockComponent;
|