반응형 레이아웃 기능 구현
This commit is contained in:
154
frontend/lib/utils/responsiveDefaults.ts
Normal file
154
frontend/lib/utils/responsiveDefaults.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 반응형 스마트 기본값 생성 유틸리티
|
||||
*/
|
||||
|
||||
import { ComponentData } from "@/types/screen-management";
|
||||
import { ResponsiveComponentConfig, BREAKPOINTS } from "@/types/responsive";
|
||||
|
||||
/**
|
||||
* 컴포넌트 크기에 따른 스마트 기본값 생성
|
||||
*
|
||||
* 로직:
|
||||
* - 작은 컴포넌트 (너비 25% 이하): 모바일에서도 같은 너비 유지
|
||||
* - 중간 컴포넌트 (너비 25-50%): 모바일에서 전체 너비로 확장
|
||||
* - 큰 컴포넌트 (너비 50% 이상): 모든 디바이스에서 전체 너비
|
||||
*/
|
||||
export function generateSmartDefaults(
|
||||
component: ComponentData,
|
||||
screenWidth: number = 1920,
|
||||
rowComponentCount: number = 1, // 같은 행에 있는 컴포넌트 개수
|
||||
): ResponsiveComponentConfig["responsive"] {
|
||||
// 특정 컴포넌트는 항상 전체 너비 (split-panel-layout, datatable 등)
|
||||
const fullWidthComponents = ["split-panel-layout", "datatable", "data-table"];
|
||||
const componentType = (component as any).componentType || component.type;
|
||||
|
||||
if (fullWidthComponents.includes(componentType)) {
|
||||
return {
|
||||
desktop: {
|
||||
gridColumns: 12, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
tablet: {
|
||||
gridColumns: 8, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
mobile: {
|
||||
gridColumns: 4, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const componentWidthPercent = (component.size.width / screenWidth) * 100;
|
||||
|
||||
// 같은 행에 여러 컴포넌트가 있으면 컬럼을 나눔
|
||||
if (rowComponentCount > 1) {
|
||||
const desktopColumns = Math.round(12 / rowComponentCount);
|
||||
const tabletColumns = Math.round(8 / rowComponentCount);
|
||||
const mobileColumns = 4; // 모바일에서는 항상 전체 너비
|
||||
|
||||
return {
|
||||
desktop: {
|
||||
gridColumns: desktopColumns,
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
tablet: {
|
||||
gridColumns: tabletColumns,
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
mobile: {
|
||||
gridColumns: mobileColumns,
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
// 작은 컴포넌트 (25% 이하)
|
||||
else if (componentWidthPercent <= 25) {
|
||||
return {
|
||||
desktop: {
|
||||
gridColumns: 3, // 12컬럼 중 3개 (25%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
tablet: {
|
||||
gridColumns: 2, // 8컬럼 중 2개 (25%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
mobile: {
|
||||
gridColumns: 1, // 4컬럼 중 1개 (25%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
// 중간 컴포넌트 (25-50%)
|
||||
else if (componentWidthPercent <= 50) {
|
||||
return {
|
||||
desktop: {
|
||||
gridColumns: 6, // 12컬럼 중 6개 (50%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
tablet: {
|
||||
gridColumns: 4, // 8컬럼 중 4개 (50%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
mobile: {
|
||||
gridColumns: 4, // 4컬럼 전체 (100%)
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
// 큰 컴포넌트 (50% 이상)
|
||||
else {
|
||||
return {
|
||||
desktop: {
|
||||
gridColumns: 12, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
tablet: {
|
||||
gridColumns: 8, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
mobile: {
|
||||
gridColumns: 4, // 전체 너비
|
||||
order: 1,
|
||||
hide: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트에 반응형 설정이 없을 경우 자동 생성
|
||||
*/
|
||||
export function ensureResponsiveConfig(component: ComponentData, screenWidth?: number): ComponentData {
|
||||
if (component.responsiveConfig) {
|
||||
return component;
|
||||
}
|
||||
|
||||
return {
|
||||
...component,
|
||||
responsiveConfig: {
|
||||
designerPosition: {
|
||||
x: component.position.x,
|
||||
y: component.position.y,
|
||||
width: component.size.width,
|
||||
height: component.size.height,
|
||||
},
|
||||
useSmartDefaults: true,
|
||||
responsive: generateSmartDefaults(component, screenWidth),
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user