Files
vexplor/frontend/lib/registry/components/image-display/ImageDisplayComponent.tsx
leeheejin 1a60177fe4 feat: 관리자 페이지 레이아웃 통일 및 JSX 구문 수정
- admin/screenMng, dataflow 페이지에 tableMng 레퍼런스 레이아웃 적용
- admin/standards 페이지 JSX 괄호 문제 수정
- 전체 관리자 페이지 UI 일관성 향상
- bg-gray-50 배경, container 구조, 통일된 제목 스타일 적용
2025-09-24 18:07:36 +09:00

157 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import React from "react";
import { ComponentRendererProps } from "@/types/component";
import { ImageDisplayConfig } from "./types";
export interface ImageDisplayComponentProps extends ComponentRendererProps {
config?: ImageDisplayConfig;
}
/**
* ImageDisplay 컴포넌트
* image-display 컴포넌트입니다
*/
export const ImageDisplayComponent: React.FC<ImageDisplayComponentProps> = ({
component,
isDesignMode = false,
isSelected = false,
onClick,
onDragStart,
onDragEnd,
config,
className,
style,
...props
}) => {
// 컴포넌트 설정
const componentConfig = {
...config,
...component.config,
} as ImageDisplayConfig;
// 스타일 계산 (위치는 RealtimePreviewDynamic에서 처리하므로 제외)
const componentStyle: React.CSSProperties = {
width: "100%",
height: "100%",
...component.style,
...style,
};
// 디자인 모드 스타일
if (isDesignMode) {
componentStyle.border = "1px dashed #cbd5e1";
componentStyle.borderColor = isSelected ? "#3b82f6" : "#cbd5e1";
}
// 이벤트 핸들러
const handleClick = (e: React.MouseEvent) => {
e.stopPropagation();
onClick?.();
};
// DOM에 전달하면 안 되는 React-specific props 필터링
const {
selectedScreen,
onZoneComponentDrop,
onZoneClick,
componentConfig: _componentConfig,
component: _component,
isSelected: _isSelected,
onClick: _onClick,
onDragStart: _onDragStart,
onDragEnd: _onDragEnd,
size: _size,
position: _position,
style: _style,
screenId: _screenId,
tableName: _tableName,
onRefresh: _onRefresh,
onClose: _onClose,
...domProps
} = props;
return (
<div style={componentStyle} className={className} {...domProps}>
{/* 라벨 렌더링 */}
{component.label && component.style?.labelDisplay !== false && (
<label
style={{
position: "absolute",
top: "-25px",
left: "0px",
fontSize: component.style?.labelFontSize || "14px",
color: component.style?.labelColor || "#3b83f6",
fontWeight: "500",
}}
>
{component.label}
{component.required && <span style={{ color: "#ef4444" }}>*</span>}
</label>
)}
<div
style={{
width: "100%",
height: "100%",
border: "1px solid #d1d5db",
borderRadius: "4px",
overflow: "hidden",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f9fafb",
}}
onClick={handleClick}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
>
{component.value || componentConfig.imageUrl ? (
<img
src={component.value || componentConfig.imageUrl}
alt={componentConfig.altText || "이미지"}
style={{
maxWidth: "100%",
maxHeight: "100%",
objectFit: componentConfig.objectFit || "contain",
}}
onError={(e) => {
(e.target as HTMLImageElement).style.display = "none";
if (e.target?.parentElement) {
e.target.parentElement.innerHTML = `
<div style="display: flex; flex-direction: column; align-items: center; gap: 8px; color: #6b7280; font-size: 14px;">
<div style="font-size: 24px;">🖼️</div>
<div>이미지 로드 실패</div>
</div>
`;
}
}}
/>
) : (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "8px",
color: "#6b7280",
fontSize: "14px",
}}
>
<div style={{ fontSize: "32px" }}>🖼</div>
<div> </div>
</div>
)}
</div>
</div>
);
};
/**
* ImageDisplay 래퍼 컴포넌트
* 추가적인 로직이나 상태 관리가 필요한 경우 사용
*/
export const ImageDisplayWrapper: React.FC<ImageDisplayComponentProps> = (props) => {
return <ImageDisplayComponent {...props} />;
};