feat(pop-text): POP 텍스트 컴포넌트 추가
- pop-text 컴포넌트 구현 (텍스트/시간/이미지/제목 타입) - PopComponentRegistry에 preview 속성 추가 - ComponentEditorPanel에서 configPanel 동적 렌더링 - PopRenderer에서 preview 컴포넌트 렌더링 지원 - ComponentPalette에 텍스트 컴포넌트 추가 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,6 +12,9 @@ import {
|
||||
} from "@/components/ui/resizable";
|
||||
import { toast } from "sonner";
|
||||
|
||||
// POP 컴포넌트 자동 등록 (반드시 다른 import보다 먼저)
|
||||
import "@/lib/registry/pop-components";
|
||||
|
||||
import PopCanvas from "./PopCanvas";
|
||||
import ComponentEditorPanel from "./panels/ComponentEditorPanel";
|
||||
import ComponentPalette from "./panels/ComponentPalette";
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { PopComponentRegistry } from "@/lib/registry/PopComponentRegistry";
|
||||
|
||||
// ========================================
|
||||
// Props
|
||||
@@ -315,6 +316,15 @@ interface ComponentSettingsFormProps {
|
||||
}
|
||||
|
||||
function ComponentSettingsForm({ component, onUpdate }: ComponentSettingsFormProps) {
|
||||
// PopComponentRegistry에서 configPanel 가져오기
|
||||
const registeredComp = PopComponentRegistry.getComponent(component.type);
|
||||
const ConfigPanel = registeredComp?.configPanel;
|
||||
|
||||
// config 업데이트 핸들러
|
||||
const handleConfigUpdate = (newConfig: any) => {
|
||||
onUpdate?.({ config: newConfig });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* 라벨 */}
|
||||
@@ -329,12 +339,19 @@ function ComponentSettingsForm({ component, onUpdate }: ComponentSettingsFormPro
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 컴포넌트 타입별 설정 (추후 구현) */}
|
||||
<div className="rounded-lg bg-gray-50 p-3">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{component.type} 전용 설정은 Phase 4에서 구현 예정
|
||||
</p>
|
||||
</div>
|
||||
{/* 컴포넌트 타입별 설정 패널 */}
|
||||
{ConfigPanel ? (
|
||||
<ConfigPanel
|
||||
config={component.config || {}}
|
||||
onUpdate={handleConfigUpdate}
|
||||
/>
|
||||
) : (
|
||||
<div className="rounded-lg bg-gray-50 p-3">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{component.type} 전용 설정이 없습니다
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useDrag } from "react-dnd";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { PopComponentType } from "../types/pop-layout";
|
||||
import { Square } from "lucide-react";
|
||||
import { Square, FileText } from "lucide-react";
|
||||
import { DND_ITEM_TYPES } from "../constants";
|
||||
|
||||
// 컴포넌트 정의
|
||||
@@ -21,6 +21,12 @@ const PALETTE_ITEMS: PaletteItem[] = [
|
||||
icon: Square,
|
||||
description: "크기 조정 테스트용",
|
||||
},
|
||||
{
|
||||
type: "pop-text",
|
||||
label: "텍스트",
|
||||
icon: FileText,
|
||||
description: "텍스트, 시간, 이미지 표시",
|
||||
},
|
||||
];
|
||||
|
||||
// 드래그 가능한 컴포넌트 아이템
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
isOverlapping,
|
||||
getAllEffectivePositions,
|
||||
} from "../utils/gridUtils";
|
||||
import { PopComponentRegistry } from "@/lib/registry/PopComponentRegistry";
|
||||
|
||||
// ========================================
|
||||
// Props
|
||||
@@ -500,7 +501,11 @@ interface ComponentContentProps {
|
||||
function ComponentContent({ component, effectivePosition, isDesignMode, isSelected }: ComponentContentProps) {
|
||||
const typeLabel = COMPONENT_TYPE_LABELS[component.type] || component.type;
|
||||
|
||||
// 디자인 모드: 플레이스홀더 표시
|
||||
// PopComponentRegistry에서 등록된 컴포넌트 가져오기
|
||||
const registeredComp = PopComponentRegistry.getComponent(component.type);
|
||||
const PreviewComponent = registeredComp?.preview;
|
||||
|
||||
// 디자인 모드: 미리보기 컴포넌트 또는 플레이스홀더 표시
|
||||
if (isDesignMode) {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
@@ -519,11 +524,15 @@ function ComponentContent({ component, effectivePosition, isDesignMode, isSelect
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 내용 */}
|
||||
<div className="flex flex-1 items-center justify-center p-2">
|
||||
<span className="text-xs text-gray-400">
|
||||
{typeLabel}
|
||||
</span>
|
||||
{/* 내용: 등록된 preview 컴포넌트 또는 기본 플레이스홀더 */}
|
||||
<div className="flex flex-1 items-center justify-center overflow-hidden">
|
||||
{PreviewComponent ? (
|
||||
<PreviewComponent config={component.config} />
|
||||
) : (
|
||||
<span className="text-xs text-gray-400 p-2">
|
||||
{typeLabel}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 위치 정보 표시 (유효 위치 사용) */}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/**
|
||||
* POP 컴포넌트 타입
|
||||
*/
|
||||
export type PopComponentType = "pop-sample"; // 테스트용 샘플 박스
|
||||
export type PopComponentType = "pop-sample" | "pop-text"; // 테스트용 샘플 박스, 텍스트 컴포넌트
|
||||
|
||||
/**
|
||||
* 데이터 흐름 정의
|
||||
@@ -341,6 +341,7 @@ export const isV5Layout = (layout: any): layout is PopLayoutDataV5 => {
|
||||
*/
|
||||
export const DEFAULT_COMPONENT_GRID_SIZE: Record<PopComponentType, { colSpan: number; rowSpan: number }> = {
|
||||
"pop-sample": { colSpan: 2, rowSpan: 1 },
|
||||
"pop-text": { colSpan: 3, rowSpan: 1 },
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user