위젯영역 리사이즈

This commit is contained in:
Macbook
2026-06-14 01:18:10 +09:00
parent 57677ef39c
commit a3dcfe5cb2
5 changed files with 336 additions and 22 deletions
+63
View File
@@ -21,17 +21,78 @@ export const FLOATING_WIDGET_LAYOUTS: FloatingWidgetLayoutPreset[] = [
{ id: '3x3', rows: 3, cols: 3, label: '3×3' },
];
export const FLOATING_WIDGET_CELL_MIN_W = 140;
export const FLOATING_WIDGET_CELL_MIN_H = 100;
export const FLOATING_WIDGET_GRID_GAP = 1;
export interface FloatingWidgetInstance {
id: string;
rows: number;
cols: number;
slots: WidgetSlot[];
/** 행·열 비율 (fr) — 그리드 칸 리사이즈 */
rowFr: number[];
colFr: number[];
position: { x: number; y: number };
width: number;
height: number;
zIndex: number;
}
export function defaultGridFr(count: number): number[] {
return Array.from({ length: count }, () => 1);
}
export function gridTemplateFr(fr: number[]): string {
return fr.map(f => `${Math.max(f, 0.05)}fr`).join(' ');
}
/** 인접 두 트랙의 fr 비율을 픽셀 delta 만큼 조정 */
export function adjustAdjacentGridFr(
fr: number[],
index: number,
deltaPx: number,
containerPx: number,
gapPx: number,
minCellPx: number,
): number[] {
if (index < 0 || index >= fr.length - 1) return fr;
const next = [...fr];
const n = fr.length;
const totalFr = fr.reduce((a, b) => a + b, 0);
const contentPx = Math.max(0, containerPx - (n - 1) * gapPx);
const pairFr = fr[index] + fr[index + 1];
const leftPx = contentPx * fr[index] / totalFr;
const rightPx = contentPx * fr[index + 1] / totalFr;
const pairPx = leftPx + rightPx;
const minLeft = Math.min(minCellPx, pairPx / 2);
const maxLeft = Math.max(pairPx - minCellPx, pairPx / 2);
const newLeftPx = Math.max(minLeft, Math.min(maxLeft, leftPx + deltaPx));
const newRightPx = pairPx - newLeftPx;
next[index] = pairFr * (newLeftPx / pairPx);
next[index + 1] = pairFr * (newRightPx / pairPx);
return next;
}
/** 스플리터 위치(px) — gap 포함 */
export function gridSplitPositions(
fr: number[],
containerPx: number,
gapPx: number,
): number[] {
const n = fr.length;
if (n <= 1 || containerPx <= 0) return [];
const totalFr = fr.reduce((a, b) => a + b, 0);
const contentPx = Math.max(0, containerPx - (n - 1) * gapPx);
const positions: number[] = [];
let accPx = 0;
for (let i = 0; i < n - 1; i++) {
accPx += contentPx * fr[i] / totalFr;
positions.push(accPx + i * gapPx + gapPx / 2);
}
return positions;
}
export function defaultSizeForGrid(rows: number, cols: number): { width: number; height: number } {
const cellW = 280;
const cellH = 220;
@@ -69,6 +130,8 @@ export function createFloatingWidgetInstance(
rows,
cols,
slots: Array.from({ length: count }, () => newWidgetSlot()),
rowFr: defaultGridFr(rows),
colFr: defaultGridFr(cols),
position: {
x: Math.min(80 + offset, Math.max(24, window.innerWidth - width - 24)),
y: Math.min(72 + offset, Math.max(24, window.innerHeight - height - 24)),