resizing
This commit is contained in:
@@ -14,6 +14,8 @@ const Spreadsheet: FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [selectedCell, setSelectedCell] = useState<{row: number, col: number} | null>(null);
|
const [selectedCell, setSelectedCell] = useState<{row: number, col: number} | null>(null);
|
||||||
|
const [columnWidths, setColumnWidths] = useState<number[]>(Array(10).fill(96)); // 96px = w-24
|
||||||
|
const [rowHeights, setRowHeights] = useState<number[]>(Array(20).fill(32)); // 32px = h-8
|
||||||
|
|
||||||
const handleCellClick = (row: number, col: number) => {
|
const handleCellClick = (row: number, col: number) => {
|
||||||
setSelectedCell({ row, col });
|
setSelectedCell({ row, col });
|
||||||
@@ -31,6 +33,22 @@ const Spreadsheet: FC = () => {
|
|||||||
return String.fromCharCode(65 + index); // A, B, C, ...
|
return String.fromCharCode(65 + index); // A, B, C, ...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleResize = (colIndex: number, newWidth: number) => {
|
||||||
|
setColumnWidths(prev => {
|
||||||
|
const newWidths = [...prev];
|
||||||
|
newWidths[colIndex] = Math.max(60, newWidth); // Минимальная ширина 60px
|
||||||
|
return newWidths;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRowResize = (rowIndex: number, newHeight: number) => {
|
||||||
|
setRowHeights(prev => {
|
||||||
|
const newHeights = [...prev];
|
||||||
|
newHeights[rowIndex] = Math.max(24, newHeight); // Минимальная высота 24px
|
||||||
|
return newHeights;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full bg-white">
|
<div className="w-full h-full bg-white">
|
||||||
{/* Formula bar */}
|
{/* Formula bar */}
|
||||||
@@ -66,9 +84,32 @@ const Spreadsheet: FC = () => {
|
|||||||
{Array.from({ length: 10 }, (_, i) => (
|
{Array.from({ length: 10 }, (_, i) => (
|
||||||
<th
|
<th
|
||||||
key={i}
|
key={i}
|
||||||
className="w-24 h-8 bg-gray-100 border border-gray-300 text-xs text-gray-600 font-medium text-center sticky top-0 z-10"
|
className="h-8 bg-gray-100 border border-gray-300 text-xs text-gray-600 font-medium text-center sticky top-0 z-10 relative"
|
||||||
|
style={{ width: columnWidths[i] }}
|
||||||
>
|
>
|
||||||
{getColumnLabel(i)}
|
{getColumnLabel(i)}
|
||||||
|
{/* Resize handle */}
|
||||||
|
<div
|
||||||
|
className="absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-blue-500 hover:bg-opacity-50"
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const startX = e.clientX;
|
||||||
|
const startWidth = columnWidths[i];
|
||||||
|
|
||||||
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
|
const newWidth = startWidth + (e.clientX - startX);
|
||||||
|
handleResize(i, newWidth);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseUp = () => {
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove);
|
||||||
|
document.removeEventListener('mouseup', handleMouseUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', handleMouseMove);
|
||||||
|
document.addEventListener('mouseup', handleMouseUp);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</th>
|
</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -77,18 +118,44 @@ const Spreadsheet: FC = () => {
|
|||||||
{cells.map((row, rowIndex) => (
|
{cells.map((row, rowIndex) => (
|
||||||
<tr key={rowIndex}>
|
<tr key={rowIndex}>
|
||||||
{/* Row header */}
|
{/* Row header */}
|
||||||
<td className="w-12 h-8 bg-gray-100 border border-gray-300 text-xs text-gray-600 font-medium text-center sticky left-0 z-10">
|
<td
|
||||||
|
className="w-12 bg-gray-100 border border-gray-300 text-xs text-gray-600 font-medium text-center sticky left-0 z-10 relative"
|
||||||
|
style={{ height: rowHeights[rowIndex] }}
|
||||||
|
>
|
||||||
{rowIndex + 1}
|
{rowIndex + 1}
|
||||||
|
{/* Resize handle */}
|
||||||
|
<div
|
||||||
|
className="absolute bottom-0 left-0 w-full h-1 cursor-row-resize hover:bg-blue-500 hover:bg-opacity-50"
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const startY = e.clientY;
|
||||||
|
const startHeight = rowHeights[rowIndex];
|
||||||
|
|
||||||
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
|
const newHeight = startHeight + (e.clientY - startY);
|
||||||
|
handleRowResize(rowIndex, newHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseUp = () => {
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove);
|
||||||
|
document.removeEventListener('mouseup', handleMouseUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', handleMouseMove);
|
||||||
|
document.addEventListener('mouseup', handleMouseUp);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
{/* Data cells */}
|
{/* Data cells */}
|
||||||
{row.map((cell, colIndex) => (
|
{row.map((cell, colIndex) => (
|
||||||
<td
|
<td
|
||||||
key={colIndex}
|
key={colIndex}
|
||||||
className={`w-24 h-8 border border-gray-300 relative cursor-cell ${
|
className={`border border-gray-300 relative cursor-cell ${
|
||||||
selectedCell?.row === rowIndex && selectedCell?.col === colIndex
|
selectedCell?.row === rowIndex && selectedCell?.col === colIndex
|
||||||
? 'bg-blue-100 border-blue-500 border-2'
|
? 'bg-blue-100 border-blue-500 border-2'
|
||||||
: 'hover:bg-gray-50'
|
: 'hover:bg-gray-50'
|
||||||
}`}
|
}`}
|
||||||
|
style={{ width: columnWidths[colIndex], height: rowHeights[rowIndex] }}
|
||||||
onClick={() => handleCellClick(rowIndex, colIndex)}
|
onClick={() => handleCellClick(rowIndex, colIndex)}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
|||||||
Reference in New Issue
Block a user