ERP-node/frontend/lib/registry/layouts/flexbox/FlexboxLayout.tsx

116 lines
3.5 KiB
TypeScript

"use client";
import React from "react";
import { LayoutRendererProps } from "../BaseLayoutRenderer";
/**
* Flexbox 레이아웃 컴포넌트
*/
export interface FlexboxLayoutProps extends LayoutRendererProps {
renderer: any; // FlexboxLayoutRenderer 타입
}
export const FlexboxLayout: React.FC<FlexboxLayoutProps> = ({
layout,
isDesignMode = false,
isSelected = false,
onClick,
className = "",
renderer,
...props
}) => {
if (!layout.layoutConfig.flexbox) {
return (
<div className="error-layout flex items-center justify-center rounded border-2 border-red-300 bg-red-50 p-4">
<div className="text-center text-red-600">
<div className="font-medium"> .</div>
<div className="mt-1 text-sm">layoutConfig.flexbox가 .</div>
</div>
</div>
);
}
const flexConfig = layout.layoutConfig.flexbox;
const containerStyle = renderer.getLayoutContainerStyle();
// 플렉스박스 스타일 설정
const flexStyle: React.CSSProperties = {
...containerStyle,
display: "flex",
flexDirection: flexConfig.direction,
justifyContent: flexConfig.justify,
alignItems: flexConfig.align,
flexWrap: flexConfig.wrap,
gap: `${flexConfig.gap}px`,
height: "100%",
width: "100%",
};
// 디자인 모드 스타일
if (isDesignMode) {
flexStyle.border = isSelected ? "2px solid #3b82f6" : "1px solid #e2e8f0";
flexStyle.borderRadius = "8px";
flexStyle.padding = "8px";
}
return (
<div
className={`flexbox-layout ${isDesignMode ? "design-mode" : ""} ${className}`}
style={flexStyle}
onClick={onClick}
draggable={isDesignMode}
onDragStart={props.onDragStart}
onDragEnd={props.onDragEnd}
{...props}
>
{layout.zones.map((zone: any) => {
const zoneChildren = renderer.getZoneChildren(zone.id);
// 플렉스 아이템 스타일 설정
const zoneStyle: React.CSSProperties = {
flex: renderer.calculateFlexValue(zone, flexConfig.direction),
};
return renderer.renderZone(zone, zoneChildren, {
style: zoneStyle,
className: "flex-zone",
});
})}
{/* 존이 없을 때 안내 메시지 */}
{layout.zones.length === 0 && (
<div
className="empty-flex-container"
style={{
flex: 1,
border: isDesignMode ? "2px dashed #cbd5e1" : "1px solid #e2e8f0",
borderRadius: "8px",
backgroundColor: isDesignMode ? "rgba(148, 163, 184, 0.05)" : "rgba(248, 250, 252, 0.5)",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: isDesignMode ? "14px" : "12px",
color: "#64748b",
minHeight: "100px",
padding: "20px",
textAlign: "center",
transition: "all 0.2s ease",
}}
onMouseEnter={(e) => {
e.currentTarget.style.borderColor = "#3b82f6";
e.currentTarget.style.backgroundColor = "rgba(59, 130, 246, 0.05)";
}}
onMouseLeave={(e) => {
e.currentTarget.style.borderColor = isDesignMode ? "#cbd5e1" : "#e2e8f0";
e.currentTarget.style.backgroundColor = isDesignMode
? "rgba(148, 163, 184, 0.05)"
: "rgba(248, 250, 252, 0.5)";
}}
>
{isDesignMode ? "플렉스박스 레이아웃에 존을 추가하세요" : "빈 레이아웃"}
</div>
)}
</div>
);
};