90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import { useState, useEffect } from "react";
|
|
|
|
interface ViewportSize {
|
|
width: number;
|
|
height: number;
|
|
availableWidth: number;
|
|
availableHeight: number;
|
|
sidebarWidth: number;
|
|
headerHeight: number;
|
|
}
|
|
|
|
/**
|
|
* 뷰포트 크기와 레이아웃 요소들을 고려한 사용 가능한 공간을 계산하는 훅
|
|
*/
|
|
export const useViewportSize = () => {
|
|
const [viewportSize, setViewportSize] = useState<ViewportSize>({
|
|
width: 0,
|
|
height: 0,
|
|
availableWidth: 0,
|
|
availableHeight: 0,
|
|
sidebarWidth: 0,
|
|
headerHeight: 0,
|
|
});
|
|
|
|
useEffect(() => {
|
|
const updateViewportSize = () => {
|
|
const width = window.innerWidth;
|
|
const height = window.innerHeight;
|
|
|
|
// 레이아웃 요소 크기 계산
|
|
const isDesktop = width >= 1024; // lg 브레이크포인트
|
|
const sidebarWidth = isDesktop ? 256 : 0; // w-64 = 256px
|
|
const headerHeight = 56; // 대략적인 헤더 높이 (h-14 = 56px)
|
|
|
|
// 사용 가능한 컨텐츠 영역 계산
|
|
const availableWidth = width - sidebarWidth;
|
|
const availableHeight = height - headerHeight;
|
|
|
|
setViewportSize({
|
|
width,
|
|
height,
|
|
availableWidth: Math.max(availableWidth, 300), // 최소 300px
|
|
availableHeight: Math.max(availableHeight, 200), // 최소 200px
|
|
sidebarWidth,
|
|
headerHeight,
|
|
});
|
|
};
|
|
|
|
updateViewportSize();
|
|
window.addEventListener("resize", updateViewportSize);
|
|
return () => window.removeEventListener("resize", updateViewportSize);
|
|
}, []);
|
|
|
|
return viewportSize;
|
|
};
|
|
|
|
/**
|
|
* 특정 컨테이너의 실제 사용 가능한 크기를 계산
|
|
*/
|
|
export const useContainerSize = (containerRef: React.RefObject<HTMLElement>) => {
|
|
const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
|
|
const viewportSize = useViewportSize();
|
|
|
|
useEffect(() => {
|
|
const updateContainerSize = () => {
|
|
if (containerRef.current) {
|
|
const rect = containerRef.current.getBoundingClientRect();
|
|
|
|
// 컨테이너 내부 여백 고려
|
|
const padding = 32; // p-4 * 2 = 32px
|
|
const controlBarHeight = 48; // 컨트롤 바 높이
|
|
|
|
const availableWidth = Math.max(rect.width - padding, 300);
|
|
const availableHeight = Math.max(rect.height - controlBarHeight - padding, 200);
|
|
|
|
setContainerSize({
|
|
width: availableWidth,
|
|
height: availableHeight,
|
|
});
|
|
}
|
|
};
|
|
|
|
updateContainerSize();
|
|
window.addEventListener("resize", updateContainerSize);
|
|
return () => window.removeEventListener("resize", updateContainerSize);
|
|
}, [containerRef, viewportSize]);
|
|
|
|
return containerSize;
|
|
};
|