318 lines
9.2 KiB
TypeScript
318 lines
9.2 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { LayoutDefinition, LayoutType, LayoutCategory } from "@/types/layout";
|
|
|
|
/**
|
|
* 레이아웃 레지스트리 클래스
|
|
* 동적으로 레이아웃 컴포넌트를 등록, 관리, 조회할 수 있는 중앙 레지스트리
|
|
*/
|
|
export class LayoutRegistry {
|
|
private static layouts = new Map<string, LayoutDefinition>();
|
|
private static eventListeners: Array<(event: LayoutRegistryEvent) => void> = [];
|
|
|
|
/**
|
|
* 레이아웃 등록
|
|
*/
|
|
static registerLayout(definition: LayoutDefinition): void {
|
|
this.layouts.set(definition.id, definition);
|
|
this.emitEvent({
|
|
type: "layout_registered",
|
|
data: definition,
|
|
timestamp: new Date(),
|
|
});
|
|
console.log(`✅ 레이아웃 등록: ${definition.id} (${definition.name})`);
|
|
|
|
// 개발자 도구 등록 (개발 모드에서만)
|
|
if (process.env.NODE_ENV === "development") {
|
|
this.registerGlobalDevTools();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 등록 해제
|
|
*/
|
|
static unregisterLayout(id: string): void {
|
|
const definition = this.layouts.get(id);
|
|
if (definition) {
|
|
this.layouts.delete(id);
|
|
this.emitEvent({
|
|
type: "layout_unregistered",
|
|
data: definition,
|
|
timestamp: new Date(),
|
|
});
|
|
console.log(`❌ 레이아웃 등록 해제: ${id}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 조회
|
|
*/
|
|
static getLayout(layoutType: string): LayoutDefinition | undefined {
|
|
return this.layouts.get(layoutType);
|
|
}
|
|
|
|
/**
|
|
* 카테고리별 레이아웃 조회
|
|
*/
|
|
static getLayoutsByCategory(category: LayoutCategory): LayoutDefinition[] {
|
|
return Array.from(this.layouts.values()).filter((layout) => layout.category === category);
|
|
}
|
|
|
|
/**
|
|
* 모든 레이아웃 조회
|
|
*/
|
|
static getAllLayouts(): LayoutDefinition[] {
|
|
return Array.from(this.layouts.values());
|
|
}
|
|
|
|
/**
|
|
* 활성화된 레이아웃만 조회
|
|
*/
|
|
static getActiveLayouts(): LayoutDefinition[] {
|
|
return Array.from(this.layouts.values()).filter((layout) => layout.isActive !== false);
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 검색
|
|
*/
|
|
static searchLayouts(query: string): LayoutDefinition[] {
|
|
const searchTerm = query.toLowerCase();
|
|
return Array.from(this.layouts.values()).filter(
|
|
(layout) =>
|
|
layout.name.toLowerCase().includes(searchTerm) ||
|
|
layout.nameEng?.toLowerCase().includes(searchTerm) ||
|
|
layout.description?.toLowerCase().includes(searchTerm) ||
|
|
layout.tags?.some((tag) => tag.toLowerCase().includes(searchTerm)),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 존재 여부 확인
|
|
*/
|
|
static hasLayout(layoutType: string): boolean {
|
|
return this.layouts.has(layoutType);
|
|
}
|
|
|
|
/**
|
|
* 등록된 레이아웃 타입 목록
|
|
*/
|
|
static getRegisteredTypes(): string[] {
|
|
return Array.from(this.layouts.keys());
|
|
}
|
|
|
|
/**
|
|
* 레이아웃 수정
|
|
*/
|
|
static updateLayout(id: string, updates: Partial<LayoutDefinition>): boolean {
|
|
const existing = this.layouts.get(id);
|
|
if (existing) {
|
|
const updated = { ...existing, ...updates };
|
|
this.layouts.set(id, updated);
|
|
this.emitEvent({
|
|
type: "layout_updated",
|
|
data: updated,
|
|
timestamp: new Date(),
|
|
});
|
|
console.log(`🔄 레이아웃 수정: ${id}`);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 대량 레이아웃 등록
|
|
*/
|
|
static registerLayouts(definitions: LayoutDefinition[]): void {
|
|
definitions.forEach((definition) => {
|
|
this.registerLayout(definition);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 레지스트리 초기화
|
|
*/
|
|
static clear(): void {
|
|
this.layouts.clear();
|
|
this.emitEvent({
|
|
type: "registry_cleared",
|
|
data: null,
|
|
timestamp: new Date(),
|
|
});
|
|
console.log("🧹 레이아웃 레지스트리 초기화");
|
|
}
|
|
|
|
/**
|
|
* 이벤트 리스너 등록
|
|
*/
|
|
static addEventListener(listener: (event: LayoutRegistryEvent) => void): void {
|
|
this.eventListeners.push(listener);
|
|
}
|
|
|
|
/**
|
|
* 이벤트 리스너 제거
|
|
*/
|
|
static removeEventListener(listener: (event: LayoutRegistryEvent) => void): void {
|
|
const index = this.eventListeners.indexOf(listener);
|
|
if (index > -1) {
|
|
this.eventListeners.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 이벤트 발생
|
|
*/
|
|
private static emitEvent(event: LayoutRegistryEvent): void {
|
|
this.eventListeners.forEach((listener) => {
|
|
try {
|
|
listener(event);
|
|
} catch (error) {
|
|
console.error("레이아웃 레지스트리 이벤트 리스너 오류:", error);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 레지스트리 상태 정보
|
|
*/
|
|
static getRegistryInfo(): {
|
|
totalLayouts: number;
|
|
activeLayouts: number;
|
|
categoryCounts: Record<LayoutCategory, number>;
|
|
registeredTypes: string[];
|
|
} {
|
|
const allLayouts = this.getAllLayouts();
|
|
const activeLayouts = this.getActiveLayouts();
|
|
|
|
const categoryCounts = allLayouts.reduce(
|
|
(acc, layout) => {
|
|
acc[layout.category] = (acc[layout.category] || 0) + 1;
|
|
return acc;
|
|
},
|
|
{} as Record<LayoutCategory, number>,
|
|
);
|
|
|
|
return {
|
|
totalLayouts: allLayouts.length,
|
|
activeLayouts: activeLayouts.length,
|
|
categoryCounts,
|
|
registeredTypes: this.getRegisteredTypes(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 개발자 도구를 브라우저 글로벌에 등록
|
|
*/
|
|
private static registerGlobalDevTools(): void {
|
|
if (typeof window !== "undefined") {
|
|
(window as any).__LAYOUT_REGISTRY__ = {
|
|
list: () => {
|
|
console.table(
|
|
this.getAllLayouts().map((l) => ({
|
|
ID: l.id,
|
|
Name: l.name,
|
|
Category: l.category,
|
|
Zones: l.defaultZones?.length || 0,
|
|
Tags: l.tags?.join(", ") || "none",
|
|
Version: l.metadata?.version || "1.0.0",
|
|
Active: l.isActive !== false ? "✅" : "❌",
|
|
})),
|
|
);
|
|
return this.getAllLayouts();
|
|
},
|
|
|
|
get: (id: string) => {
|
|
const layout = this.getLayout(id);
|
|
if (layout) {
|
|
console.group(`📦 Layout: ${id}`);
|
|
console.log("Definition:", layout);
|
|
console.log("Component:", layout.component);
|
|
console.log("Config:", layout.defaultConfig);
|
|
console.log("Zones:", layout.defaultZones);
|
|
console.groupEnd();
|
|
return layout;
|
|
} else {
|
|
console.warn(`❌ Layout not found: ${id}`);
|
|
console.log("Available layouts:", this.getRegisteredTypes());
|
|
return null;
|
|
}
|
|
},
|
|
|
|
stats: () => {
|
|
const info = this.getRegistryInfo();
|
|
console.group("📊 Layout Registry Statistics");
|
|
console.log(`📦 Total Layouts: ${info.totalLayouts}`);
|
|
console.log(`✅ Active Layouts: ${info.activeLayouts}`);
|
|
console.log("📂 Categories:", info.categoryCounts);
|
|
console.log("🏷️ Registered Types:", info.registeredTypes);
|
|
console.groupEnd();
|
|
return info;
|
|
},
|
|
|
|
search: (query: string) => {
|
|
const results = this.searchLayouts(query);
|
|
console.log(`🔍 Search results for "${query}":`, results);
|
|
return results;
|
|
},
|
|
|
|
categories: () => {
|
|
const byCategory = this.getAllLayouts().reduce(
|
|
(acc, layout) => {
|
|
if (!acc[layout.category]) acc[layout.category] = [];
|
|
acc[layout.category].push(layout.id);
|
|
return acc;
|
|
},
|
|
{} as Record<string, string[]>,
|
|
);
|
|
|
|
console.table(byCategory);
|
|
return byCategory;
|
|
},
|
|
|
|
clear: () => {
|
|
console.warn("🧹 Clearing layout registry...");
|
|
this.clear();
|
|
console.log("✅ Registry cleared");
|
|
},
|
|
|
|
reload: () => {
|
|
console.log("🔄 Registry reload not implemented yet");
|
|
console.log("Try refreshing the page or using HMR");
|
|
},
|
|
|
|
help: () => {
|
|
console.group("🛠️ Layout Registry DevTools Help");
|
|
console.log("__LAYOUT_REGISTRY__.list() - 모든 레이아웃 목록 표시");
|
|
console.log("__LAYOUT_REGISTRY__.get(id) - 특정 레이아웃 상세 정보");
|
|
console.log("__LAYOUT_REGISTRY__.stats() - 레지스트리 통계");
|
|
console.log("__LAYOUT_REGISTRY__.search(query) - 레이아웃 검색");
|
|
console.log("__LAYOUT_REGISTRY__.categories() - 카테고리별 레이아웃");
|
|
console.log("__LAYOUT_REGISTRY__.clear() - 레지스트리 초기화");
|
|
console.log("__LAYOUT_REGISTRY__.help() - 도움말");
|
|
console.groupEnd();
|
|
},
|
|
};
|
|
|
|
// 첫 등록 시에만 안내 메시지 출력
|
|
if (!(window as any).__LAYOUT_REGISTRY_INITIALIZED__) {
|
|
console.log("🛠️ Layout Registry DevTools initialized!");
|
|
console.log("Use __LAYOUT_REGISTRY__.help() for available commands");
|
|
(window as any).__LAYOUT_REGISTRY_INITIALIZED__ = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 레지스트리 이벤트 타입
|
|
export interface LayoutRegistryEvent {
|
|
type: "layout_registered" | "layout_unregistered" | "layout_updated" | "registry_cleared";
|
|
data: LayoutDefinition | null;
|
|
timestamp: Date;
|
|
}
|
|
|
|
// 전역 레이아웃 레지스트리 인스턴스 (싱글톤)
|
|
export const layoutRegistry = LayoutRegistry;
|
|
|
|
// 기본 내보내기
|
|
export default LayoutRegistry;
|