Try fix 2 step
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import React, { useRef, useState, useMemo } from 'react';
|
import React, { useRef, useState, useMemo } from 'react';
|
||||||
import { AppConfig, LayoutSplits } from '../types';
|
import { AppConfig, LayoutSplits } from '../types';
|
||||||
// ИСПРАВЛЕНИЕ: Используем безопасные иконки
|
// Заменили иконки на Columns/Rows (они есть везде)
|
||||||
import { Grid, MousePointer2, Trash2, RotateCcw, LayoutGrid, X, Plus, Minus, RectangleHorizontal, RectangleVertical } from 'lucide-react';
|
import { Grid, MousePointer2, Trash2, RotateCcw, LayoutGrid, X, Plus, Minus, Columns, Rows } from 'lucide-react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
config: AppConfig;
|
config: AppConfig;
|
||||||
@@ -23,15 +23,19 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
|||||||
const [isButtonHovered, setIsButtonHovered] = useState(false);
|
const [isButtonHovered, setIsButtonHovered] = useState(false);
|
||||||
const [selectedCell, setSelectedCell] = useState<{ i: number, j: number } | null>(null);
|
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 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 viewBoxH = viewBoxW * aspectRatio;
|
||||||
|
|
||||||
const sortedX = useMemo(() => [0, ...splits.x, 1].sort((a, b) => a - b), [splits.x]);
|
const sortedX = useMemo(() => [0, ...safeX, 1].sort((a, b) => a - b), [safeX]);
|
||||||
const sortedY = useMemo(() => [0, ...splits.y, 1].sort((a, b) => a - b), [splits.y]);
|
const sortedY = useMemo(() => [0, ...safeY, 1].sort((a, b) => a - b), [safeY]);
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: Безопасное получение subdivisions (если вдруг undefined)
|
|
||||||
const safeSubdivisions = splits.subdivisions || {};
|
|
||||||
|
|
||||||
const getSubdivision = (i: number, j: number) => {
|
const getSubdivision = (i: number, j: number) => {
|
||||||
return safeSubdivisions[`${i}-${j}`] || { rows: 1, cols: 1 };
|
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 (mode === 'lines') {
|
||||||
if (dragging) {
|
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;
|
const val = dragging.axis === 'x' ? nx : ny;
|
||||||
newSplits[dragging.axis][dragging.index] = val;
|
newSplits[dragging.axis][dragging.index] = val;
|
||||||
onChange(newSplits);
|
onChange(newSplits);
|
||||||
@@ -75,8 +79,8 @@ export const LayoutStep: React.FC<Props> = ({ config, splits, onChange }) => {
|
|||||||
setHoveredSplit(null);
|
setHoveredSplit(null);
|
||||||
|
|
||||||
const SNAP = 0.02;
|
const SNAP = 0.02;
|
||||||
const closeToX = splits.x.some(val => Math.abs(nx - val) < SNAP);
|
const closeToX = safeX.some(val => Math.abs(nx - val) < SNAP);
|
||||||
const closeToY = splits.y.some(val => Math.abs(ny - val) < SNAP);
|
const closeToY = safeY.some(val => Math.abs(ny - val) < SNAP);
|
||||||
const closeToEdgeX = nx < SNAP || nx > (1 - SNAP);
|
const closeToEdgeX = nx < SNAP || nx > (1 - SNAP);
|
||||||
const closeToEdgeY = ny < SNAP || ny > (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 (e.button === 2) removeSplit(hoveredSplit.axis, hoveredSplit.index);
|
||||||
} else if (phantomAxis && !isButtonHovered) {
|
} else if (phantomAxis && !isButtonHovered) {
|
||||||
const val = phantomAxis === 'x' ? mousePos.x : mousePos.y;
|
const val = phantomAxis === 'x' ? mousePos.x : mousePos.y;
|
||||||
const newSplits = { ...splits };
|
const newSplits = { ...splits, x: [...safeX], y: [...safeY] };
|
||||||
newSplits[phantomAxis] = [...newSplits[phantomAxis], val];
|
newSplits[phantomAxis] = [...newSplits[phantomAxis], val];
|
||||||
onChange(newSplits);
|
onChange(newSplits);
|
||||||
setDragging({ axis: phantomAxis, index: newSplits[phantomAxis].length - 1 });
|
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 removeSplit = (axis: Axis, index: number) => {
|
||||||
const newSplits = { ...splits };
|
const newSplits = { ...splits, x: [...safeX], y: [...safeY] };
|
||||||
newSplits[axis] = newSplits[axis].filter((_, i) => i !== index);
|
newSplits[axis] = newSplits[axis].filter((_, i) => i !== index);
|
||||||
onChange(newSplits);
|
onChange(newSplits);
|
||||||
setHoveredSplit(null);
|
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)}>
|
<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="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" />
|
<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>
|
</g>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{splits.y.map((y, i) => (
|
{safeY.map((y, i) => (
|
||||||
<g key={`y-${i}`} onMouseMove={(e) => handleSplitHover(e, '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="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" />
|
<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>
|
</svg>
|
||||||
|
|
||||||
{/* --- МЕНЮ ДЛЯ ЯЧЕЙКИ (С ИСПРАВЛЕННЫМИ ИКОНКАМИ) --- */}
|
|
||||||
{mode === 'cells' && selectedCell && (
|
{mode === 'cells' && selectedCell && (
|
||||||
<div
|
<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"
|
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()}
|
onMouseDown={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{/* Ряды */}
|
|
||||||
<div className="flex items-center gap-2">
|
<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>
|
<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>
|
<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>
|
<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>
|
||||||
|
|
||||||
{/* Колонки */}
|
|
||||||
<div className="flex items-center gap-2">
|
<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>
|
<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>
|
<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>
|
<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