feat: TableListComponent 컬럼 너비 드래그 조절 기능 추가
- 실제 화면에서 사용되는 TableListComponent에도 리사이즈 기능 추가 - InteractiveDataTable과 동일한 리사이즈 핸들 구현 - columnWidths 상태로 각 컬럼 너비 관리 - 드래그 중 텍스트 선택 방지 및 이벤트 전파 차단 - 최소 너비 80px 보장
This commit is contained in:
parent
107f722e7a
commit
787bfd363f
|
|
@ -244,6 +244,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [draggedRowIndex, setDraggedRowIndex] = useState<number | null>(null);
|
||||
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
|
||||
const [isAllSelected, setIsAllSelected] = useState(false);
|
||||
|
||||
// 필터 설정 관련 상태
|
||||
|
|
@ -1018,31 +1019,75 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
className="sticky top-0 z-10 bg-background"
|
||||
>
|
||||
<tr className="h-10 border-b border-border sm:h-12">
|
||||
{visibleColumns.map((column) => (
|
||||
<th
|
||||
key={column.columnName}
|
||||
className={cn(
|
||||
"h-10 px-2 py-2 text-xs font-semibold text-foreground overflow-hidden text-ellipsis bg-background sm:h-12 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap",
|
||||
column.sortable && "cursor-pointer"
|
||||
)}
|
||||
style={{
|
||||
textAlign: column.align || "left",
|
||||
width: `${100 / visibleColumns.length}%`, // 컬럼 수에 따라 균등 분배
|
||||
}}
|
||||
onClick={() => column.sortable && handleSort(column.columnName)}
|
||||
>
|
||||
{column.columnName === "__checkbox__" ? (
|
||||
renderCheckboxHeader()
|
||||
) : (
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<span>{columnLabels[column.columnName] || column.displayName}</span>
|
||||
{column.sortable && sortColumn === column.columnName && (
|
||||
<span>{sortDirection === "asc" ? "↑" : "↓"}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</th>
|
||||
))}
|
||||
{visibleColumns.map((column, columnIndex) => {
|
||||
const columnWidth = columnWidths[column.columnName];
|
||||
const defaultWidth = `${100 / visibleColumns.length}%`;
|
||||
|
||||
return (
|
||||
<th
|
||||
key={column.columnName}
|
||||
className={cn(
|
||||
"relative h-10 px-2 py-2 text-xs font-semibold text-foreground overflow-hidden text-ellipsis bg-background select-none sm:h-12 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap",
|
||||
column.sortable && "cursor-pointer"
|
||||
)}
|
||||
style={{
|
||||
textAlign: column.align || "left",
|
||||
width: columnWidth ? `${columnWidth}px` : defaultWidth,
|
||||
minWidth: '80px',
|
||||
userSelect: 'none'
|
||||
}}
|
||||
onClick={() => column.sortable && handleSort(column.columnName)}
|
||||
>
|
||||
{column.columnName === "__checkbox__" ? (
|
||||
renderCheckboxHeader()
|
||||
) : (
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
<span>{columnLabels[column.columnName] || column.displayName}</span>
|
||||
{column.sortable && sortColumn === column.columnName && (
|
||||
<span>{sortDirection === "asc" ? "↑" : "↓"}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/* 리사이즈 핸들 */}
|
||||
{columnIndex < visibleColumns.length - 1 && (
|
||||
<div
|
||||
className="absolute right-0 top-0 h-full w-1 cursor-col-resize hover:bg-blue-500"
|
||||
onClick={(e) => e.stopPropagation()} // 정렬 클릭 방지
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const startX = e.clientX;
|
||||
const startWidth = columnWidth || (e.currentTarget.parentElement?.offsetWidth || 100);
|
||||
|
||||
// 드래그 중 텍스트 선택 방지
|
||||
document.body.style.userSelect = 'none';
|
||||
document.body.style.cursor = 'col-resize';
|
||||
|
||||
const handleMouseMove = (moveEvent: MouseEvent) => {
|
||||
moveEvent.preventDefault();
|
||||
const diff = moveEvent.clientX - startX;
|
||||
const newWidth = Math.max(80, startWidth + diff);
|
||||
setColumnWidths(prev => ({ ...prev, [column.columnName]: newWidth }));
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
// 텍스트 선택 복원
|
||||
document.body.style.userSelect = '';
|
||||
document.body.style.cursor = '';
|
||||
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</th>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue