탭 분할

This commit is contained in:
kjs 2026-01-05 16:14:36 +09:00
parent a3c29b28ad
commit 3fdc9e36f4
1 changed files with 55 additions and 157 deletions

View File

@ -2,24 +2,10 @@
import React, { useState, useMemo } from "react";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ComponentRegistry } from "@/lib/registry/ComponentRegistry";
import { ComponentDefinition, ComponentCategory } from "@/types/component";
import {
Search,
Package,
Grid,
Layers,
Palette,
Zap,
MousePointer,
Edit3,
BarChart3,
Database,
Wrench,
Sparkles,
} from "lucide-react";
import { Search, Package, Grid, Layers, Palette, Zap, MousePointer, Database } from "lucide-react";
import { TableInfo, ColumnInfo } from "@/types/screen";
import TablesPanel from "./TablesPanel";
@ -67,8 +53,9 @@ export function ComponentsPanel({
// Unified 컴포넌트 정의 (새로운 통합 컴포넌트 시스템)
// 입력 컴포넌트(unified-input, unified-select, unified-date)는 테이블 컬럼 드래그 시 자동 생성되므로 숨김
const unifiedComponents: ComponentDefinition[] = useMemo(
() => [
const unifiedComponents = useMemo(
() =>
[
// unified-input: 테이블 컬럼 드래그 시 자동 생성되므로 숨김 처리
// unified-select: 테이블 컬럼 드래그 시 자동 생성되므로 숨김 처리
// unified-date: 테이블 컬럼 드래그 시 자동 생성되므로 숨김 처리
@ -77,9 +64,9 @@ export function ComponentsPanel({
{
id: "unified-list",
name: "통합 목록",
description: "테이블, 카드, 칸반, 리스트 등 다양한 데이터 표시 방식 지원",
description: "테이블, 카드 등 다양한 데이터 표시 방식 지원",
category: "display" as ComponentCategory,
tags: ["table", "list", "card", "kanban", "unified"],
tags: ["table", "list", "card", "unified"],
defaultSize: { width: 600, height: 400 },
},
// unified-media 제거 - 테이블 컬럼의 image/file 입력 타입으로 사용
@ -93,7 +80,7 @@ export function ComponentsPanel({
tags: ["repeater", "table", "modal", "button", "unified"],
defaultSize: { width: 600, height: 300 },
},
],
] as ComponentDefinition[],
[],
);
@ -270,87 +257,20 @@ export function ComponentsPanel({
</div>
</div>
{/* 카테고리 탭 */}
<Tabs defaultValue="unified" className="flex min-h-0 flex-1 flex-col">
<TabsList className="mb-3 grid h-16 w-full flex-shrink-0 grid-cols-4 grid-rows-2 gap-1 p-1">
{/* 1행: Unified, 테이블, 입력, 데이터 */}
<TabsTrigger
value="unified"
className="bg-primary/10 data-[state=active]:bg-primary flex items-center justify-center gap-0.5 px-0 text-[10px] data-[state=active]:text-white"
title="Unified 컴포넌트"
>
<Sparkles className="h-3 w-3" />
<span className="text-[9px]">Unified</span>
</TabsTrigger>
<TabsTrigger
value="tables"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="테이블"
>
{/* 테이블 / 컴포넌트 탭 */}
<Tabs defaultValue="tables" className="flex min-h-0 flex-1 flex-col">
<TabsList className="mb-3 grid h-8 w-full shrink-0 grid-cols-2 gap-1 p-1">
<TabsTrigger value="tables" className="flex items-center justify-center gap-1 text-xs">
<Database className="h-3 w-3" />
<span className="text-[9px]"></span>
<span></span>
</TabsTrigger>
<TabsTrigger value="input" className="flex items-center justify-center gap-0.5 px-0 text-[10px]" title="입력">
<Edit3 className="h-3 w-3" />
<span className="text-[9px]"></span>
</TabsTrigger>
<TabsTrigger
value="data"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="데이터"
>
<Grid className="h-3 w-3" />
<span className="text-[9px]"></span>
</TabsTrigger>
{/* 2행: 액션, 표시, 레이아웃, 유틸리티 */}
<TabsTrigger
value="action"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="액션"
>
<Zap className="h-3 w-3" />
<span className="text-[9px]"></span>
</TabsTrigger>
<TabsTrigger
value="display"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="표시"
>
<BarChart3 className="h-3 w-3" />
<span className="text-[9px]"></span>
</TabsTrigger>
<TabsTrigger
value="layout"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="레이아웃"
>
<Layers className="h-3 w-3" />
<span className="text-[9px]"></span>
</TabsTrigger>
<TabsTrigger
value="utility"
className="flex items-center justify-center gap-0.5 px-0 text-[10px]"
title="유틸리티"
>
<Wrench className="h-3 w-3" />
<span className="text-[9px]"></span>
<TabsTrigger value="components" className="flex items-center justify-center gap-1 text-xs">
<Package className="h-3 w-3" />
<span></span>
</TabsTrigger>
</TabsList>
{/* Unified 컴포넌트 탭 */}
<TabsContent value="unified" className="mt-0 flex-1 space-y-2 overflow-y-auto">
<div className="bg-primary/5 border-primary/20 mb-2 rounded-md border p-2">
<p className="text-muted-foreground text-[10px] leading-relaxed">
<span className="text-primary font-semibold">Unified </span>
.
</p>
</div>
{getFilteredComponents("unified").length > 0
? getFilteredComponents("unified").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 테이블 탭 */}
{/* 테이블 컬럼 탭 */}
<TabsContent value="tables" className="mt-0 flex-1 overflow-y-auto">
{tables.length > 0 && onTableDragStart ? (
<TablesPanel
@ -366,51 +286,29 @@ export function ComponentsPanel({
<div className="p-6">
<Database className="text-muted-foreground/40 mx-auto mb-2 h-10 w-10" />
<p className="text-muted-foreground text-xs font-medium"> </p>
<p className="text-muted-foreground/60 mt-1 text-xs"> </p>
</div>
</div>
)}
</TabsContent>
{/* 입력 컴포넌트 */}
<TabsContent value="input" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("input").length > 0
? getFilteredComponents("input").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 컴포넌트 탭 */}
<TabsContent value="components" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{(() => {
const allFilteredComponents = [
...getFilteredComponents("unified"),
...getFilteredComponents("action"),
...getFilteredComponents("display"),
...getFilteredComponents("data"),
...getFilteredComponents("layout"),
...getFilteredComponents("input"),
...getFilteredComponents("utility"),
];
{/* 데이터 컴포넌트 */}
<TabsContent value="data" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("data").length > 0
? getFilteredComponents("data").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 액션 컴포넌트 */}
<TabsContent value="action" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("action").length > 0
? getFilteredComponents("action").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 표시 컴포넌트 */}
<TabsContent value="display" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("display").length > 0
? getFilteredComponents("display").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 레이아웃 컴포넌트 */}
<TabsContent value="layout" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("layout").length > 0
? getFilteredComponents("layout").map(renderComponentCard)
: renderEmptyState()}
</TabsContent>
{/* 유틸리티 컴포넌트 */}
<TabsContent value="utility" className="mt-0 flex-1 space-y-2 overflow-y-auto">
{getFilteredComponents("utility").length > 0
? getFilteredComponents("utility").map(renderComponentCard)
: renderEmptyState()}
return allFilteredComponents.length > 0
? allFilteredComponents.map(renderComponentCard)
: renderEmptyState();
})()}
</TabsContent>
</Tabs>