Try fix 2 step
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React, { useRef, useState, useMemo } from 'react';
|
||||
import { AppConfig, LayoutSplits } from '../types';
|
||||
// ИСПРАВЛЕНИЕ: Используем безопасные иконки
|
||||
import { Grid, MousePointer2, Trash2, RotateCcw, LayoutGrid, X, Plus, Minus, RectangleHorizontal, RectangleVertical } from 'lucide-react';
|
||||
// Заменили иконки на Columns/Rows (они есть везде)
|
||||
import { Grid, MousePointer2, Trash2, RotateCcw, LayoutGrid, X, Plus, Minus, Columns, Rows } from 'lucide-react';
|
||||
|
||||
interface Props {
|
||||
config: AppConfig;
|
||||
@@ -23,16 +23,20 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
const [isButtonHovered, setIsButtonHovered] = useState(false);
|
||||
const [selectedCell, setSelectedCell] = useState<{ i: number, j: number } | null>(null);
|
||||
|
||||
// --- ЗАЩИТА ОТ СБОЕВ ---
|
||||
// Если splits или массивы не инициализированы, используем пустые значения
|
||||
const safeX = splits?.x || [];
|
||||
const safeY = splits?.y || [];
|
||||
const safeSubdivisions = splits?.subdivisions || {};
|
||||
|
||||
const viewBoxW = 1000;
|
||||
const aspectRatio = config.drawer.depth / config.drawer.width;
|
||||
// Защита от деления на ноль
|
||||
const aspectRatio = (config.drawer.depth || 1) / (config.drawer.width || 1);
|
||||
const viewBoxH = viewBoxW * aspectRatio;
|
||||
|
||||
const sortedX = useMemo(() => [0, ...splits.x, 1].sort((a, b) => a - b), [splits.x]);
|
||||
const sortedY = useMemo(() => [0, ...splits.y, 1].sort((a, b) => a - b), [splits.y]);
|
||||
const sortedX = useMemo(() => [0, ...safeX, 1].sort((a, b) => a - b), [safeX]);
|
||||
const sortedY = useMemo(() => [0, ...safeY, 1].sort((a, b) => a - b), [safeY]);
|
||||
|
||||
// ИСПРАВЛЕНИЕ: Безопасное получение subdivisions (если вдруг undefined)
|
||||
const safeSubdivisions = splits.subdivisions || {};
|
||||
|
||||
const getSubdivision = (i: number, j: number) => {
|
||||
return safeSubdivisions[`${i}-${j}`] || { rows: 1, cols: 1 };
|
||||
};
|
||||
@@ -63,7 +67,7 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
|
||||
if (mode === 'lines') {
|
||||
if (dragging) {
|
||||
const newSplits = { ...splits, x: [...splits.x], y: [...splits.y] };
|
||||
const newSplits = { ...splits, x: [...safeX], y: [...safeY] };
|
||||
const val = dragging.axis === 'x' ? nx : ny;
|
||||
newSplits[dragging.axis][dragging.index] = val;
|
||||
onChange(newSplits);
|
||||
@@ -75,8 +79,8 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
setHoveredSplit(null);
|
||||
|
||||
const SNAP = 0.02;
|
||||
const closeToX = splits.x.some(val => Math.abs(nx - val) < SNAP);
|
||||
const closeToY = splits.y.some(val => Math.abs(ny - val) < SNAP);
|
||||
const closeToX = safeX.some(val => Math.abs(nx - val) < SNAP);
|
||||
const closeToY = safeY.some(val => Math.abs(ny - val) < SNAP);
|
||||
const closeToEdgeX = nx < SNAP || nx > (1 - SNAP);
|
||||
const closeToEdgeY = ny < SNAP || ny > (1 - SNAP);
|
||||
|
||||
@@ -105,7 +109,7 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
else if (e.button === 2) removeSplit(hoveredSplit.axis, hoveredSplit.index);
|
||||
} else if (phantomAxis && !isButtonHovered) {
|
||||
const val = phantomAxis === 'x' ? mousePos.x : mousePos.y;
|
||||
const newSplits = { ...splits };
|
||||
const newSplits = { ...splits, x: [...safeX], y: [...safeY] };
|
||||
newSplits[phantomAxis] = [...newSplits[phantomAxis], val];
|
||||
onChange(newSplits);
|
||||
setDragging({ axis: phantomAxis, index: newSplits[phantomAxis].length - 1 });
|
||||
@@ -116,7 +120,7 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
};
|
||||
|
||||
const removeSplit = (axis: Axis, index: number) => {
|
||||
const newSplits = { ...splits };
|
||||
const newSplits = { ...splits, x: [...safeX], y: [...safeY] };
|
||||
newSplits[axis] = newSplits[axis].filter((_, i) => i !== index);
|
||||
onChange(newSplits);
|
||||
setHoveredSplit(null);
|
||||
@@ -261,7 +265,7 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
});
|
||||
})}
|
||||
|
||||
{splits.x.map((x, i) => (
|
||||
{safeX.map((x, i) => (
|
||||
<g key={`x-${i}`} onMouseMove={(e) => handleSplitHover(e, 'x', i)}>
|
||||
<line x1={x * viewBoxW} y1={0} x2={x * viewBoxW} y2={viewBoxH} stroke="transparent" strokeWidth="60" className={mode === 'lines' ? "cursor-col-resize" : ""} />
|
||||
<line x1={x * viewBoxW} y1={0} x2={x * viewBoxW} y2={viewBoxH} stroke="#f59e0b" strokeWidth="4" className="pointer-events-none" />
|
||||
@@ -276,7 +280,7 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
</g>
|
||||
))}
|
||||
|
||||
{splits.y.map((y, i) => (
|
||||
{safeY.map((y, i) => (
|
||||
<g key={`y-${i}`} onMouseMove={(e) => handleSplitHover(e, 'y', i)}>
|
||||
<line x1={0} y1={y * viewBoxH} x2={viewBoxW} y2={y * viewBoxH} stroke="transparent" strokeWidth="60" className={mode === 'lines' ? "cursor-row-resize" : ""} />
|
||||
<line x1={0} y1={y * viewBoxH} x2={viewBoxW} y2={y * viewBoxH} stroke="#f59e0b" strokeWidth="4" className="pointer-events-none" />
|
||||
@@ -305,7 +309,6 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
)}
|
||||
</svg>
|
||||
|
||||
{/* --- МЕНЮ ДЛЯ ЯЧЕЙКИ (С ИСПРАВЛЕННЫМИ ИКОНКАМИ) --- */}
|
||||
{mode === 'cells' && selectedCell && (
|
||||
<div
|
||||
className="absolute flex flex-col gap-2 p-2 bg-slate-800/90 backdrop-blur rounded-lg border border-blue-500 shadow-2xl transform -translate-x-1/2 -translate-y-1/2"
|
||||
@@ -315,17 +318,15 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
||||
}}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Ряды */}
|
||||
<div className="flex items-center gap-2">
|
||||
<RectangleVertical size={16} className="text-blue-400" />
|
||||
<Columns size={16} className="text-blue-400" />
|
||||
<button onClick={() => updateSubdivision(selectedCell.i, selectedCell.j, 'cols', -1)} className="w-6 h-6 bg-slate-700 hover:bg-slate-600 rounded flex items-center justify-center"><Minus size={12}/></button>
|
||||
<span className="font-mono font-bold w-4 text-center">{getSubdivision(selectedCell.i, selectedCell.j).cols}</span>
|
||||
<button onClick={() => updateSubdivision(selectedCell.i, selectedCell.j, 'cols', 1)} className="w-6 h-6 bg-slate-700 hover:bg-slate-600 rounded flex items-center justify-center"><Plus size={12}/></button>
|
||||
</div>
|
||||
|
||||
{/* Колонки */}
|
||||
<div className="flex items-center gap-2">
|
||||
<RectangleHorizontal size={16} className="text-blue-400" />
|
||||
<Rows size={16} className="text-blue-400" />
|
||||
<button onClick={() => updateSubdivision(selectedCell.i, selectedCell.j, 'rows', -1)} className="w-6 h-6 bg-slate-700 hover:bg-slate-600 rounded flex items-center justify-center"><Minus size={12}/></button>
|
||||
<span className="font-mono font-bold w-4 text-center">{getSubdivision(selectedCell.i, selectedCell.j).rows}</span>
|
||||
<button onClick={() => updateSubdivision(selectedCell.i, selectedCell.j, 'rows', 1)} className="w-6 h-6 bg-slate-700 hover:bg-slate-600 rounded flex items-center justify-center"><Plus size={12}/></button>
|
||||
|
||||
Reference in New Issue
Block a user