ERP-node/frontend/lib/utils/gridUtils.ts

199 lines
5.2 KiB
TypeScript

import { Position, Size } from "@/types/screen";
import { GridSettings } from "@/types/screen-management";
// 🎯 10px 고정 격자 시스템
const GRID_SIZE = 10; // 고정값
export interface GridInfo {
gridSize: number; // 항상 10px
totalWidth: number;
totalHeight: number;
}
/**
* 격자 정보 계산 (단순화)
*/
export function calculateGridInfo(
containerWidth: number,
containerHeight: number,
_gridSettings?: GridSettings, // 호환성 유지용 (사용 안 함)
): GridInfo {
return {
gridSize: GRID_SIZE,
totalWidth: containerWidth,
totalHeight: containerHeight,
};
}
/**
* 위치를 10px 격자에 맞춤
*/
export function snapToGrid(position: Position, _gridInfo: GridInfo, gridSettings: GridSettings): Position {
if (!gridSettings.snapToGrid) {
return position;
}
return {
x: Math.round(position.x / GRID_SIZE) * GRID_SIZE,
y: Math.round(position.y / GRID_SIZE) * GRID_SIZE,
z: position.z,
};
}
/**
* 크기를 10px 격자에 맞춤
*/
export function snapSizeToGrid(size: Size, _gridInfo: GridInfo, gridSettings: GridSettings): Size {
if (!gridSettings.snapToGrid) {
return size;
}
return {
width: Math.max(GRID_SIZE, Math.round(size.width / GRID_SIZE) * GRID_SIZE),
height: Math.max(GRID_SIZE, Math.round(size.height / GRID_SIZE) * GRID_SIZE),
};
}
/**
* 격자 가이드라인 생성 (10px 간격)
*/
export function generateGridLines(
containerWidth: number,
containerHeight: number,
_gridSettings?: GridSettings,
): {
verticalLines: number[];
horizontalLines: number[];
} {
const verticalLines: number[] = [];
for (let x = 0; x <= containerWidth; x += GRID_SIZE) {
verticalLines.push(x);
}
const horizontalLines: number[] = [];
for (let y = 0; y <= containerHeight; y += GRID_SIZE) {
horizontalLines.push(y);
}
return {
verticalLines,
horizontalLines,
};
}
/**
* 컴포넌트가 격자 경계에 있는지 확인
*/
export function isOnGridBoundary(
position: Position,
size: Size,
gridInfo: GridInfo,
gridSettings: GridSettings,
tolerance: number = 5,
): boolean {
const snappedPos = snapToGrid(position, gridInfo, gridSettings);
const snappedSize = snapSizeToGrid(size, gridInfo, gridSettings);
const positionMatch =
Math.abs(position.x - snappedPos.x) <= tolerance && Math.abs(position.y - snappedPos.y) <= tolerance;
const sizeMatch =
Math.abs(size.width - snappedSize.width) <= tolerance && Math.abs(size.height - snappedSize.height) <= tolerance;
return positionMatch && sizeMatch;
}
/**
* 그룹 내부 컴포넌트들을 격자에 맞게 정렬
*/
export function alignGroupChildrenToGrid(
children: any[],
groupPosition: Position,
gridInfo: GridInfo,
gridSettings: GridSettings,
): any[] {
if (!gridSettings.snapToGrid || children.length === 0) return children;
return children.map((child) => {
const padding = 16;
// 10px 단위로 스냅
const snappedX = Math.max(padding, Math.round((child.position.x - padding) / GRID_SIZE) * GRID_SIZE + padding);
const snappedY = Math.max(padding, Math.round((child.position.y - padding) / GRID_SIZE) * GRID_SIZE + padding);
const snappedWidth = Math.max(GRID_SIZE, Math.round(child.size.width / GRID_SIZE) * GRID_SIZE);
const snappedHeight = Math.max(GRID_SIZE, Math.round(child.size.height / GRID_SIZE) * GRID_SIZE);
return {
...child,
position: {
x: snappedX,
y: snappedY,
z: child.position.z || 1,
},
size: {
width: snappedWidth,
height: snappedHeight,
},
};
});
}
/**
* 그룹 생성 시 최적화된 그룹 크기 계산
*/
export function calculateOptimalGroupSize(
children: Array<{ position: Position; size: Size }>,
_gridInfo?: GridInfo,
_gridSettings?: GridSettings,
): Size {
if (children.length === 0) {
return { width: GRID_SIZE * 20, height: GRID_SIZE * 10 };
}
const bounds = children.reduce(
(acc, child) => ({
minX: Math.min(acc.minX, child.position.x),
minY: Math.min(acc.minY, child.position.y),
maxX: Math.max(acc.maxX, child.position.x + child.size.width),
maxY: Math.max(acc.maxY, child.position.y + child.size.height),
}),
{ minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },
);
const contentWidth = bounds.maxX - bounds.minX;
const contentHeight = bounds.maxY - bounds.minY;
const padding = 16;
return {
width: contentWidth + padding * 2,
height: contentHeight + padding * 2,
};
}
/**
* 그룹 내 상대 좌표를 격자 기준으로 정규화
*/
export function normalizeGroupChildPositions(children: any[], _gridSettings?: GridSettings): any[] {
if (children.length === 0) return children;
const minX = Math.min(...children.map((child) => child.position.x));
const minY = Math.min(...children.map((child) => child.position.y));
const padding = 16;
return children.map((child) => ({
...child,
position: {
x: child.position.x - minX + padding,
y: child.position.y - minY + padding,
z: child.position.z || 1,
},
}));
}
// 🗑️ 제거된 함수들 (더 이상 필요 없음)
// - calculateWidthFromColumns
// - updateSizeFromGridColumns
// - adjustGridColumnsFromSize
// - calculateColumnsFromWidth