ERP-node/lib/registry/DynamicWebTypeRenderer.tsx

104 lines
3.1 KiB
TypeScript
Raw Permalink Normal View History

2025-09-09 14:29:04 +09:00
"use client";
import React, { Suspense } from "react";
import { WebTypeRegistry } from "./WebTypeRegistry";
import { WebTypeComponentProps } from "./types";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Loader2 } from "lucide-react";
interface DynamicWebTypeRendererProps extends WebTypeComponentProps {
widgetType: string;
fallback?: React.ComponentType<WebTypeComponentProps>;
showError?: boolean;
}
/**
*
*
*/
export const DynamicWebTypeRenderer: React.FC<DynamicWebTypeRendererProps> =
React.memo(
({
widgetType,
component,
fallback: FallbackComponent,
showError = true,
...props
}) => {
// 웹타입 정의 조회
const definition = WebTypeRegistry.get(widgetType);
// 웹타입이 등록되지 않은 경우
if (!definition) {
console.warn(`Unknown web type: ${widgetType}`);
// Fallback 컴포넌트가 있으면 사용
if (FallbackComponent) {
return <FallbackComponent component={component} {...props} />;
}
// 에러 표시를 원하지 않으면 빈 div 반환
if (!showError) {
return <div className="w-full h-full" />;
}
// 에러 메시지 표시
return (
<Alert variant="destructive" className="w-full">
<AlertDescription>
: <code>{widgetType}</code>
</AlertDescription>
</Alert>
);
}
// 비활성화된 웹타입인 경우
if (definition.isActive === false) {
console.warn(`Inactive web type: ${widgetType}`);
if (showError) {
return (
<Alert variant="secondary" className="w-full">
<AlertDescription>
: <code>{widgetType}</code>
</AlertDescription>
</Alert>
);
}
return <div className="w-full h-full opacity-50" />;
}
// 등록된 컴포넌트 렌더링
const Component = definition.component;
return (
<Suspense
fallback={
<div className="flex items-center justify-center w-full h-full p-2">
<Loader2 className="h-4 w-4 animate-spin text-gray-400" />
<span className="ml-2 text-xs text-gray-500"> ...</span>
</div>
}
>
<Component component={component} {...props} />
</Suspense>
);
},
(prevProps, nextProps) => {
// 메모이제이션을 위한 얕은 비교
return (
prevProps.widgetType === nextProps.widgetType &&
prevProps.component.id === nextProps.component.id &&
prevProps.value === nextProps.value &&
prevProps.readonly === nextProps.readonly &&
JSON.stringify(prevProps.component.webTypeConfig) ===
JSON.stringify(nextProps.component.webTypeConfig)
);
}
);
DynamicWebTypeRenderer.displayName = "DynamicWebTypeRenderer";