fix: Section Paper 선택 영역과 컨텐츠 영역 정렬 문제 해결
- RealtimePreview: border → outline 전환, getHeight() 함수 추가 - SectionPaperComponent: width/height 100%, overflow-auto, min-h 제거 - 모든 높이에서 선택 영역 = 컨텐츠 영역 정확히 일치
This commit is contained in:
parent
e456b4bb69
commit
2b8a3945a1
|
|
@ -401,22 +401,10 @@ export const RealtimePreviewDynamic: React.FC<RealtimePreviewProps> = ({
|
|||
|
||||
// 컴포넌트 스타일 계산
|
||||
const isFlowWidget = type === "flow" || (type === "component" && (component as any).componentConfig?.type === "flow-widget");
|
||||
const isSectionPaper = type === "component" && (component as any).componentConfig?.type === "section-paper";
|
||||
|
||||
// 높이 결정 로직
|
||||
let finalHeight = size?.height || 10;
|
||||
if (isFlowWidget && actualHeight) {
|
||||
finalHeight = actualHeight;
|
||||
}
|
||||
|
||||
// 🔍 디버깅: position.x 값 확인
|
||||
const positionX = position?.x || 0;
|
||||
console.log("🔍 RealtimePreview componentStyle 설정:", {
|
||||
componentId: id,
|
||||
positionX,
|
||||
sizeWidth: size?.width,
|
||||
styleWidth: style?.width,
|
||||
willUse100Percent: positionX === 0,
|
||||
});
|
||||
const positionY = position?.y || 0;
|
||||
|
||||
// 너비 결정 로직: style.width (퍼센트) > 조건부 100% > size.width (픽셀)
|
||||
const getWidth = () => {
|
||||
|
|
@ -432,20 +420,35 @@ export const RealtimePreviewDynamic: React.FC<RealtimePreviewProps> = ({
|
|||
return size?.width || 200;
|
||||
};
|
||||
|
||||
// 높이 결정 로직: style.height > actualHeight (Flow Widget) > size.height
|
||||
const getHeight = () => {
|
||||
// 1순위: style.height가 있으면 우선 사용 (픽셀/퍼센트 값)
|
||||
if (style?.height) {
|
||||
return style.height;
|
||||
}
|
||||
// 2순위: Flow Widget의 실제 측정 높이
|
||||
if (isFlowWidget && actualHeight) {
|
||||
return actualHeight;
|
||||
}
|
||||
// 3순위: size.height 픽셀 값
|
||||
return size?.height || 10;
|
||||
};
|
||||
|
||||
const componentStyle = {
|
||||
position: "absolute" as const,
|
||||
...style, // 먼저 적용하고
|
||||
left: positionX,
|
||||
top: position?.y || 0,
|
||||
top: positionY,
|
||||
width: getWidth(), // 우선순위에 따른 너비
|
||||
height: finalHeight,
|
||||
height: getHeight(), // 우선순위에 따른 높이
|
||||
zIndex: position?.z || 1,
|
||||
// right 속성 강제 제거
|
||||
right: undefined,
|
||||
};
|
||||
|
||||
// 선택된 컴포넌트 스타일
|
||||
const selectionStyle = isSelected
|
||||
// Section Paper는 자체적으로 선택 상태 테두리를 처리하므로 outline 제거
|
||||
const selectionStyle = isSelected && !isSectionPaper
|
||||
? {
|
||||
outline: "2px solid rgb(59, 130, 246)",
|
||||
outlineOffset: "2px",
|
||||
|
|
@ -628,6 +631,24 @@ export const RealtimePreviewDynamic: React.FC<RealtimePreviewProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* 컴포넌트 타입 - 레지스트리 기반 렌더링 (Section Paper, Section Card 등) */}
|
||||
{type === "component" && (() => {
|
||||
const { DynamicComponentRenderer } = require("@/lib/registry/DynamicComponentRenderer");
|
||||
return (
|
||||
<DynamicComponentRenderer
|
||||
component={component}
|
||||
isSelected={isSelected}
|
||||
isDesignMode={isDesignMode}
|
||||
onClick={onClick}
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={onDragEnd}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</DynamicComponentRenderer>
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* 위젯 타입 - 동적 렌더링 (파일 컴포넌트 제외) */}
|
||||
{type === "widget" && !isFileComponent(component) && (
|
||||
<div className="h-full w-full">
|
||||
|
|
|
|||
|
|
@ -4603,10 +4603,11 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
});
|
||||
}}
|
||||
>
|
||||
{/* 컨테이너, 그룹, 영역의 자식 컴포넌트들 렌더링 (레이아웃은 독립적으로 렌더링) */}
|
||||
{/* 컨테이너, 그룹, 영역, 컴포넌트의 자식 컴포넌트들 렌더링 (레이아웃은 독립적으로 렌더링) */}
|
||||
{(component.type === "group" ||
|
||||
component.type === "container" ||
|
||||
component.type === "area") &&
|
||||
component.type === "area" ||
|
||||
component.type === "component") &&
|
||||
layout.components
|
||||
.filter((child) => child.parentId === component.id)
|
||||
.map((child) => {
|
||||
|
|
|
|||
|
|
@ -83,11 +83,22 @@ export function SectionPaperComponent({
|
|||
? { backgroundColor: config.customColor }
|
||||
: {};
|
||||
|
||||
// 선택 상태 테두리 처리 (outline 사용하여 크기 영향 없음)
|
||||
const selectionStyle = isDesignMode && isSelected
|
||||
? {
|
||||
outline: "2px solid #3b82f6",
|
||||
outlineOffset: "0px", // 크기에 영향 없이 딱 맞게 표시
|
||||
}
|
||||
: {};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
// 기본 스타일
|
||||
"relative transition-colors overflow-visible",
|
||||
"relative transition-colors",
|
||||
|
||||
// 높이 고정을 위한 overflow 처리
|
||||
"overflow-auto",
|
||||
|
||||
// 배경색
|
||||
backgroundColor !== "custom" && backgroundColorMap[backgroundColor],
|
||||
|
|
@ -101,37 +112,36 @@ export function SectionPaperComponent({
|
|||
// 그림자
|
||||
shadowMap[shadow],
|
||||
|
||||
// 테두리 (선택)
|
||||
showBorder &&
|
||||
// 테두리 (선택 상태가 아닐 때만)
|
||||
!isSelected && showBorder &&
|
||||
borderStyle === "subtle" &&
|
||||
"border border-border/30",
|
||||
|
||||
// 디자인 모드에서 선택된 상태
|
||||
isDesignMode && isSelected && "ring-2 ring-primary ring-offset-2",
|
||||
|
||||
// 디자인 모드에서 빈 상태 표시
|
||||
isDesignMode && !children && "min-h-[100px] border-2 border-dashed border-muted-foreground/30",
|
||||
// 디자인 모드에서 빈 상태 표시 (테두리만, 최소 높이 제거)
|
||||
isDesignMode && !children && "border-2 border-dashed border-muted-foreground/30",
|
||||
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
// 크기를 100%로 설정하여 부모 크기에 맞춤
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
boxSizing: "border-box", // padding과 border를 크기에 포함
|
||||
...customBgStyle,
|
||||
...component?.style,
|
||||
...selectionStyle,
|
||||
...component?.style, // 사용자 설정이 최종 우선순위
|
||||
}}
|
||||
onClick={onClick}
|
||||
>
|
||||
{/* 디자인 모드에서 빈 상태 안내 */}
|
||||
{isDesignMode && !children && (
|
||||
{/* 자식 컴포넌트들 */}
|
||||
{children || (isDesignMode && (
|
||||
<div className="flex items-center justify-center h-full text-muted-foreground text-sm">
|
||||
<div className="text-center">
|
||||
<div className="mb-1">📄 Section Paper</div>
|
||||
<div className="text-xs">컴포넌트를 이곳에 배치하세요</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 자식 컴포넌트들 */}
|
||||
{children}
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue