refactor: 격자 시스템을 10px 단위로 단순화

- 복잡한 컬럼 시스템 제거
- 웹타입별 고정 픽셀 너비 사용 (10px 단위)
- 격자 설정 패널 단순화 (컬럼 수 설정 제거)
- 간격/여백 조정을 10px 단위로 변경
- 더 직관적이고 예측 가능한 레이아웃 시스템
This commit is contained in:
kjs 2025-11-10 14:41:58 +09:00
parent 7ab3781372
commit c4290f2d0e
2 changed files with 47 additions and 138 deletions

View File

@ -2338,45 +2338,43 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
snapToGrid: layout.gridSettings?.snapToGrid,
});
// 웹타입별 기본 그리드 컬럼 수 계산
const getDefaultGridColumns = (widgetType: string): number => {
// 웹타입별 기본 너비 계산 (10px 단위 고정)
const getDefaultWidth = (widgetType: string): number => {
const widthMap: Record<string, number> = {
// 텍스트 입력 계열 (넓게)
text: 4, // 1/3 (33%)
email: 4, // 1/3 (33%)
tel: 3, // 1/4 (25%)
url: 4, // 1/3 (33%)
textarea: 6, // 절반 (50%)
// 텍스트 입력 계열
text: 200,
email: 200,
tel: 150,
url: 250,
textarea: 300,
// 숫자/날짜 입력 (중간)
number: 2, // 2/12 (16.67%)
decimal: 2, // 2/12 (16.67%)
date: 3, // 1/4 (25%)
datetime: 3, // 1/4 (25%)
time: 2, // 2/12 (16.67%)
// 숫자/날짜 입력
number: 120,
decimal: 120,
date: 150,
datetime: 180,
time: 120,
// 선택 입력 (중간)
select: 3, // 1/4 (25%)
radio: 3, // 1/4 (25%)
checkbox: 2, // 2/12 (16.67%)
boolean: 2, // 2/12 (16.67%)
// 선택 입력
select: 180,
radio: 180,
checkbox: 120,
boolean: 120,
// 코드/참조 (넓게)
code: 3, // 1/4 (25%)
entity: 4, // 1/3 (33%)
// 코드/참조
code: 180,
entity: 200,
// 파일/이미지 (넓게)
file: 4, // 1/3 (33%)
image: 3, // 1/4 (25%)
// 파일/이미지
file: 250,
image: 200,
// 기타
button: 2, // 2/12 (16.67%)
label: 2, // 2/12 (16.67%)
button: 100,
label: 100,
};
const defaultColumns = widthMap[widgetType] || 3; // 기본값 3 (1/4, 25%)
console.log("🎯 [ScreenDesigner] getDefaultGridColumns:", { widgetType, defaultColumns });
return defaultColumns;
return widthMap[widgetType] || 200; // 기본값 200px
};
// 웹타입별 기본 높이 계산
@ -2544,24 +2542,12 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
const componentId = getComponentIdFromWebType(column.widgetType);
// console.log(`🔄 폼 컨테이너 드롭: ${column.widgetType} → ${componentId}`);
// 웹타입별 적절한 gridColumns 계산
const calculatedGridColumns = getDefaultGridColumns(column.widgetType);
// gridColumns에 맞는 실제 너비 계산
const componentWidth =
currentGridInfo && layout.gridSettings?.snapToGrid
? calculateWidthFromColumns(
calculatedGridColumns,
currentGridInfo,
layout.gridSettings as GridUtilSettings,
)
: defaultWidth;
// 웹타입별 기본 너비 계산 (10px 단위 고정)
const componentWidth = getDefaultWidth(column.widgetType);
console.log("🎯 폼 컨테이너 컴포넌트 생성:", {
widgetType: column.widgetType,
calculatedGridColumns,
componentWidth,
defaultWidth,
});
newComponent = {
@ -2576,7 +2562,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
componentType: componentId, // DynamicComponentRenderer용 컴포넌트 타입
position: { x: relativeX, y: relativeY, z: 1 } as Position,
size: { width: componentWidth, height: getDefaultHeight(column.widgetType) },
gridColumns: calculatedGridColumns,
// 코드 타입인 경우 코드 카테고리 정보 추가
...(column.widgetType === "code" &&
column.codeCategory && {
@ -2588,7 +2573,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
labelColor: "#212121",
labelFontWeight: "500",
labelMarginBottom: "6px",
width: `${(calculatedGridColumns / (layout.gridSettings?.columns || 12)) * 100}%`, // 퍼센트 너비
},
componentConfig: {
type: componentId, // text-input, number-input 등
@ -2611,36 +2595,14 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
const componentId = getComponentIdFromWebType(column.widgetType);
// console.log(`🔄 캔버스 드롭: ${column.widgetType} → ${componentId}`);
// 웹타입별 적절한 gridColumns 계산
const calculatedGridColumns = getDefaultGridColumns(column.widgetType);
// gridColumns에 맞는 실제 너비 계산
const componentWidth =
currentGridInfo && layout.gridSettings?.snapToGrid
? calculateWidthFromColumns(
calculatedGridColumns,
currentGridInfo,
layout.gridSettings as GridUtilSettings,
)
: defaultWidth;
// 웹타입별 기본 너비 계산 (10px 단위 고정)
const componentWidth = getDefaultWidth(column.widgetType);
console.log("🎯 캔버스 컴포넌트 생성:", {
widgetType: column.widgetType,
calculatedGridColumns,
componentWidth,
defaultWidth,
});
// 🔍 이미지 타입 드래그앤드롭 디버깅
// if (column.widgetType === "image") {
// console.log("🖼️ 이미지 컬럼 드래그앤드롭:", {
// columnName: column.columnName,
// widgetType: column.widgetType,
// componentId,
// column,
// });
// }
newComponent = {
id: generateComponentId(),
type: "component", // ✅ 새로운 컴포넌트 시스템 사용
@ -2652,7 +2614,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
componentType: componentId, // DynamicComponentRenderer용 컴포넌트 타입
position: { x, y, z: 1 } as Position,
size: { width: componentWidth, height: getDefaultHeight(column.widgetType) },
gridColumns: calculatedGridColumns,
// 코드 타입인 경우 코드 카테고리 정보 추가
...(column.widgetType === "code" &&
column.codeCategory && {
@ -2664,7 +2625,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
labelColor: "#000000", // 순수한 검정
labelFontWeight: "500",
labelMarginBottom: "8px",
width: `${(calculatedGridColumns / (layout.gridSettings?.columns || 12)) * 100}%`, // 퍼센트 너비
},
componentConfig: {
type: componentId, // text-input, number-input 등

View File

@ -128,49 +128,14 @@ export const GridPanel: React.FC<GridPanelProps> = ({
{/* 설정 영역 */}
<div className="flex-1 space-y-4 overflow-y-auto p-4">
{/* 격자 구조 */}
{/* 격자 구조 - 10px 단위 */}
<div className="space-y-3">
<h4 className="text-xs font-semibold"> </h4>
<h4 className="text-xs font-semibold"> (10px )</h4>
<div className="space-y-2">
<Label htmlFor="columns" className="text-xs font-medium">
</Label>
<div className="flex items-center gap-2">
<Input
id="columns"
type="number"
min={1}
max={safeMaxColumns}
value={gridSettings.columns}
onChange={(e) => {
const value = parseInt(e.target.value, 10);
if (!isNaN(value) && value >= 1 && value <= safeMaxColumns) {
updateSetting("columns", value);
}
}}
className="h-8 text-xs"
/>
<span className="text-muted-foreground text-xs">/ {safeMaxColumns}</span>
</div>
<Slider
id="columns-slider"
min={1}
max={safeMaxColumns}
step={1}
value={[gridSettings.columns]}
onValueChange={([value]) => updateSetting("columns", value)}
className="w-full"
/>
<div className="text-muted-foreground flex justify-between text-xs">
<span>1</span>
<span>{safeMaxColumns}</span>
</div>
{isColumnsTooSmall && (
<p className="text-xs text-amber-600">
( {MIN_COLUMN_WIDTH}px )
</p>
)}
<div className="bg-muted/50 rounded-md p-3">
<p className="text-xs text-muted-foreground">
10px .
</p>
</div>
<div className="space-y-2">
@ -181,7 +146,7 @@ export const GridPanel: React.FC<GridPanelProps> = ({
id="gap"
min={0}
max={40}
step={2}
step={10}
value={[gridSettings.gap]}
onValueChange={([value]) => updateSetting("gap", value)}
className="w-full"
@ -200,7 +165,7 @@ export const GridPanel: React.FC<GridPanelProps> = ({
id="padding"
min={0}
max={60}
step={4}
step={10}
value={[gridSettings.padding]}
onValueChange={([value]) => updateSetting("padding", value)}
className="w-full"
@ -288,14 +253,14 @@ export const GridPanel: React.FC<GridPanelProps> = ({
<div className="border-t border-gray-200 bg-gray-50 p-3">
<div className="text-muted-foreground text-xs">💡 </div>
{/* 해상도 및 격자 정보 */}
{screenResolution && actualGridInfo && (
{/* 해상도 정보 */}
{screenResolution && (
<>
<Separator />
<div className="space-y-3">
<h4 className="font-medium text-gray-900"> </h4>
<div className="space-y-2">
<h4 className="text-xs font-semibold"> </h4>
<div className="space-y-2 text-xs" style={{ fontSize: "12px" }}>
<div className="space-y-2 text-xs">
<div className="flex justify-between">
<span className="text-muted-foreground">:</span>
<span className="font-mono">
@ -304,25 +269,9 @@ export const GridPanel: React.FC<GridPanelProps> = ({
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className={`font-mono ${isColumnsTooSmall ? "text-destructive" : "text-gray-900"}`}>
{actualGridInfo.columnWidth.toFixed(1)}px
{isColumnsTooSmall && " (너무 작음)"}
</span>
<span className="text-muted-foreground"> :</span>
<span className="font-mono text-primary">10px</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground"> :</span>
<span className="font-mono">
{(screenResolution.width - gridSettings.padding * 2).toLocaleString()}px
</span>
</div>
{isColumnsTooSmall && (
<div className="rounded-md bg-yellow-50 p-2 text-xs text-yellow-800">
💡 . .
</div>
)}
</div>
</div>
</>