"use client"; import React from "react"; import { BaseLayoutRenderer, LayoutRendererProps } from "./BaseLayoutRenderer"; export default class FlexboxLayoutRenderer extends BaseLayoutRenderer { render(): React.ReactElement { const { layout, isDesignMode, isSelected, onClick, className } = this.props; if (!layout.layoutConfig.flexbox) { return
플렉스박스 설정이 없습니다.
; } const flexConfig = layout.layoutConfig.flexbox; const containerStyle = this.getLayoutContainerStyle(); // 플렉스박스 스타일 설정 const flexStyle: React.CSSProperties = { ...containerStyle, display: "flex", flexDirection: flexConfig.direction, justifyContent: flexConfig.justify, alignItems: flexConfig.align, flexWrap: flexConfig.wrap, gap: `${flexConfig.gap}px`, }; // 디자인 모드 스타일 if (isDesignMode) { flexStyle.border = isSelected ? "2px solid #3b82f6" : "1px solid #e2e8f0"; flexStyle.borderRadius = "8px"; flexStyle.padding = "8px"; } return (
{layout.zones.map((zone, index) => { const zoneChildren = this.getZoneChildren(zone.id); // 플렉스 아이템 스타일 설정 const zoneStyle: React.CSSProperties = { flex: this.calculateFlexValue(zone, flexConfig.direction), }; return this.renderZone(zone, zoneChildren, { style: zoneStyle, className: "flex-zone", }); })} {/* 존이 없을 때 안내 메시지 */} {layout.zones.length === 0 && (
{ 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 ? "플렉스박스 레이아웃에 존을 추가하세요" : "빈 레이아웃"}
)}
); } /** * 플렉스 아이템의 flex 값을 계산합니다. */ private calculateFlexValue(zone: any, direction: string): string { // 존의 크기에 따라 flex 값 결정 if (direction === "row" || direction === "row-reverse") { // 가로 방향: width를 기준으로 flex 값 계산 if (typeof zone.size.width === "string") { if (zone.size.width.includes("fr")) { return zone.size.width.replace("fr", ""); } else if (zone.size.width.includes("%")) { const percent = parseInt(zone.size.width.replace("%", "")); return `0 0 ${percent}%`; } else if (zone.size.width.includes("px")) { return `0 0 ${zone.size.width}`; } } else if (typeof zone.size.width === "number") { return `0 0 ${zone.size.width}px`; } } else { // 세로 방향: height를 기준으로 flex 값 계산 if (typeof zone.size.height === "string") { if (zone.size.height.includes("fr")) { return zone.size.height.replace("fr", ""); } else if (zone.size.height.includes("%")) { const percent = parseInt(zone.size.height.replace("%", "")); return `0 0 ${percent}%`; } else if (zone.size.height.includes("px")) { return `0 0 ${zone.size.height}`; } } else if (typeof zone.size.height === "number") { return `0 0 ${zone.size.height}px`; } } // 기본값: 균등 분할 return "1"; } } // React 컴포넌트로 래핑 export const FlexboxLayout: React.FC = (props) => { const renderer = new FlexboxLayoutRenderer(props); return renderer.render(); };