diff --git a/src/components/LayoutStep.tsx b/src/components/LayoutStep.tsx index 23dd414..8f0ea63 100644 --- a/src/components/LayoutStep.tsx +++ b/src/components/LayoutStep.tsx @@ -1,6 +1,6 @@ import React, { useRef, useState, useMemo } from 'react'; import { AppConfig, LayoutSplits, Partition } from '../types'; -import { Grid, MousePointer2, Trash2, RotateCcw, X, Move } from 'lucide-react'; +import { Grid, MousePointer2, Trash2, RotateCcw, X, Plus } from 'lucide-react'; interface Props { config: AppConfig; @@ -24,26 +24,23 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { // Состояния const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); const [isButtonHovered, setIsButtonHovered] = useState(false); + const [dragging, setDragging] = useState(null); - // Main Grid States + // Main Grid const [phantomMainAxis, setPhantomMainAxis] = useState(null); const [hoveredMainSplit, setHoveredMainSplit] = useState<{ axis: Axis; index: number } | null>(null); - // Partition States + // Partitions const [hoveredCell, setHoveredCell] = useState<{ i: number; j: number } | null>(null); const [hoveredPartition, setHoveredPartition] = useState<{ id: string; cellKey: string } | null>(null); const [phantomPartition, setPhantomPartition] = useState<{ axis: Axis; offset: number } | null>(null); - - // Selection & Dragging const [selectedPartitionId, setSelectedPartitionId] = useState(null); - const [dragging, setDragging] = useState(null); // --- Safe Data --- const safeX = Array.isArray(splits?.x) ? splits.x : []; const safeY = Array.isArray(splits?.y) ? splits.y : []; const safePartitions = splits?.partitions || {}; - // Размеры const drawerW = Math.max(1, config.drawer.width || 300); const drawerD = Math.max(1, config.drawer.depth || 400); const aspectRatio = drawerD / drawerW; @@ -54,7 +51,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { const sortedX = useMemo(() => [0, ...safeX, 1].sort((a, b) => a - b), [safeX]); const sortedY = useMemo(() => [0, ...safeY, 1].sort((a, b) => a - b), [safeY]); - // --- Helper --- + // --- Helpers --- const getSelectedPartition = () => { if (!selectedPartitionId) return null; for (const key in safePartitions) { @@ -65,7 +62,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { }; const selectedData = getSelectedPartition(); - // --- ACTIONS --- + // --- Actions --- const removeMainSplit = (axis: Axis, index: number) => { const newSplits = { ...splits, x: [...safeX], y: [...safeY] }; newSplits[axis] = newSplits[axis].filter((_, i) => i !== index); @@ -80,10 +77,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { const current = safePartitions[key] || []; const newPart: Partition = { id: Math.random().toString(36).substr(2, 9), - axis, - offset, - height: config.drawer.height || 80, - rounded: false + axis, offset, height: config.drawer.height || 80, rounded: false }; onChange({ ...splits, partitions: { ...safePartitions, [key]: [...current, newPart] } }); setSelectedPartitionId(newPart.id); @@ -102,7 +96,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { setHoveredPartition(null); }; - // --- MOUSE HANDLER --- + // --- Mouse Handlers --- const handleMouseMove = (e: React.MouseEvent) => { if (!svgRef.current) return; const rect = svgRef.current.getBoundingClientRect(); @@ -132,7 +126,9 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { newOffset = (ny - cellY1) / (cellY2 - cellY1); } newOffset = Math.max(0.05, Math.min(0.95, newOffset)); - updatePartition(pDrag.cellKey, pDrag.id, { offset: newOffset }); + if (!isNaN(newOffset)) { + updatePartition(pDrag.cellKey, pDrag.id, { offset: newOffset }); + } } return; } @@ -141,7 +137,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { if (mode === 'lines') { setHoveredMainSplit(null); - const SNAP = 0.015; + const SNAP = 0.015; if (nx > SNAP && nx < 1-SNAP && ny > SNAP && ny < 1-SNAP) { const closeToX = safeX.some(val => Math.abs(nx - val) < SNAP); const closeToY = safeY.some(val => Math.abs(ny - val) < SNAP); @@ -256,18 +252,10 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => {

2. Редактор макета

-
- - + +
- @@ -319,7 +307,8 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { {sortedX.slice(0, -1).map((x1, i) => { const x2 = sortedX[i + 1]; return sortedY.slice(0, -1).map((y1, j) => { - const y2 = sortedY[j + 1]; // ВОТ ЭТО ИСПРАВЛЕНО + // ЯВНОЕ ОПРЕДЕЛЕНИЕ ПЕРЕМЕННОЙ Y2 + const y2 = sortedY[j + 1]; const cellX = x1 * viewBoxW; const cellY = y1 * viewBoxH; const cellW = (x2 - x1) * viewBoxW; const cellH = (y2 - y1) * viewBoxH; @@ -331,18 +320,17 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { return ( - {/* Highlight Cell */} + {/* Highlight */} {isHovered && } {isAnyPartSelected && mode === 'cells' && } - {/* Existing Partitions */} + {/* Partitions */} {parts.map(p => { const isSelected = selectedPartitionId === p.id; const isHoveredPart = hoveredPartition?.id === p.id; let lx1, ly1, lx2, ly2; if (p.axis === 'x') { const px = cellX + (cellW * p.offset); lx1 = px; ly1 = cellY; lx2 = px; ly2 = cellY + cellH; } else { const py = cellY + (cellH * p.offset); lx1 = cellX; ly1 = py; lx2 = cellX + cellW; ly2 = py; } - return ( { e.stopPropagation(); removePartition(key, p.id); }}> @@ -350,8 +338,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { ); })} - - {/* Phantom Partition */} + {/* Phantom */} {isHovered && phantomPartition && !hoveredPartition && !dragging && ( {phantomPartition.axis === 'x' ? @@ -385,7 +372,7 @@ export const LayoutStep: React.FC = ({ config, splits, onChange }) => { ); })} - {/* PHANTOMS */} + {/* MAIN PHANTOMS */} {mode === 'lines' && !hoveredMainSplit && !dragging && phantomMainAxis === 'x' && } {mode === 'lines' && !hoveredMainSplit && !dragging && phantomMainAxis === 'y' && }