feat: 카테고리 위젯에 드래그 가능한 리사이저 추가
- 좌우 영역을 드래그로 조절 가능 - 리사이저: GripVertical 아이콘으로 시각적 표시 - 좌측 영역: 최소 10%, 최대 40%로 제한 - 호버 시 배경색 변경으로 피드백 제공 - 드래그 중 커서 및 텍스트 선택 방지
This commit is contained in:
parent
4b568f86b1
commit
fe306aed26
|
|
@ -1,8 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useRef, useCallback } from "react";
|
||||
import { CategoryColumnList } from "@/components/table-category/CategoryColumnList";
|
||||
import { CategoryValueManager } from "@/components/table-category/CategoryValueManager";
|
||||
import { GripVertical } from "lucide-react";
|
||||
|
||||
interface CategoryWidgetProps {
|
||||
widgetId: string;
|
||||
|
|
@ -19,11 +20,49 @@ export function CategoryWidget({ widgetId, tableName }: CategoryWidgetProps) {
|
|||
columnName: string;
|
||||
columnLabel: string;
|
||||
} | null>(null);
|
||||
|
||||
const [leftWidth, setLeftWidth] = useState(15); // 초기값 15%
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const isDraggingRef = useRef(false);
|
||||
|
||||
const handleMouseDown = useCallback(() => {
|
||||
isDraggingRef.current = true;
|
||||
document.body.style.cursor = "col-resize";
|
||||
document.body.style.userSelect = "none";
|
||||
}, []);
|
||||
|
||||
const handleMouseMove = useCallback((e: MouseEvent) => {
|
||||
if (!isDraggingRef.current || !containerRef.current) return;
|
||||
|
||||
const containerRect = containerRef.current.getBoundingClientRect();
|
||||
const newLeftWidth = ((e.clientX - containerRect.left) / containerRect.width) * 100;
|
||||
|
||||
// 최소 10%, 최대 40%로 제한
|
||||
if (newLeftWidth >= 10 && newLeftWidth <= 40) {
|
||||
setLeftWidth(newLeftWidth);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleMouseUp = useCallback(() => {
|
||||
isDraggingRef.current = false;
|
||||
document.body.style.cursor = "";
|
||||
document.body.style.userSelect = "";
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
document.addEventListener("mousemove", handleMouseMove);
|
||||
document.addEventListener("mouseup", handleMouseUp);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
document.removeEventListener("mouseup", handleMouseUp);
|
||||
};
|
||||
}, [handleMouseMove, handleMouseUp]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-[10px] gap-6">
|
||||
{/* 좌측: 카테고리 컬럼 리스트 (15%) */}
|
||||
<div className="w-[15%] border-r pr-6">
|
||||
<div ref={containerRef} className="flex h-full min-h-[10px] gap-0">
|
||||
{/* 좌측: 카테고리 컬럼 리스트 */}
|
||||
<div style={{ width: `${leftWidth}%` }} className="pr-3">
|
||||
<CategoryColumnList
|
||||
tableName={tableName}
|
||||
selectedColumn={selectedColumn?.columnName || null}
|
||||
|
|
@ -33,8 +72,16 @@ export function CategoryWidget({ widgetId, tableName }: CategoryWidgetProps) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* 우측: 카테고리 값 관리 (85%) */}
|
||||
<div className="w-[85%]">
|
||||
{/* 리사이저 */}
|
||||
<div
|
||||
onMouseDown={handleMouseDown}
|
||||
className="group relative flex w-3 cursor-col-resize items-center justify-center border-r hover:bg-accent/50 transition-colors"
|
||||
>
|
||||
<GripVertical className="h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors" />
|
||||
</div>
|
||||
|
||||
{/* 우측: 카테고리 값 관리 */}
|
||||
<div style={{ width: `${100 - leftWidth - 1}%` }} className="pl-3">
|
||||
{selectedColumn ? (
|
||||
<CategoryValueManager
|
||||
tableName={tableName}
|
||||
|
|
|
|||
Loading…
Reference in New Issue