위젯의 최소 크기를 1x1 로 변경

This commit is contained in:
dohyeons 2025-10-28 15:02:37 +09:00
parent 71beae8e24
commit 28ecc31128
6 changed files with 34 additions and 32 deletions

View File

@ -353,9 +353,9 @@ export function CanvasElement({
let newX = resizeStart.elementX; let newX = resizeStart.elementX;
let newY = resizeStart.elementY; let newY = resizeStart.elementY;
// 최소 크기 설정: 달력은 2x3, 나머지는 2x2 // 최소 크기 설정: 모든 위젯 1x1
const minWidthCells = 2; const minWidthCells = 1;
const minHeightCells = element.type === "widget" && element.subtype === "calendar" ? 3 : 2; const minHeightCells = 1;
const minWidth = cellSize * minWidthCells; const minWidth = cellSize * minWidthCells;
const minHeight = cellSize * minHeightCells; const minHeight = cellSize * minHeightCells;

View File

@ -242,12 +242,12 @@ export function ChartRenderer({ element, data, width, height = 200 }: ChartRende
// D3 차트 렌더링 // D3 차트 렌더링
const actualWidth = width !== undefined ? width : containerWidth; const actualWidth = width !== undefined ? width : containerWidth;
// 원형 차트는 더 큰 크기가 필요 (최소 400px) // 최소 크기 제약 완화 (1x1 위젯 지원)
const isCircularChart = element.subtype === "pie" || element.subtype === "donut"; const isCircularChart = element.subtype === "pie" || element.subtype === "donut";
const minWidth = isCircularChart ? 400 : 200; const minWidth = 35; // 최소 너비 35px
const finalWidth = Math.max(actualWidth - 20, minWidth); const finalWidth = Math.max(actualWidth - 4, minWidth);
// 원형 차트는 범례 공간을 위해 더 많은 여백 필요 // 최소 높이도 35px로 설정
const finalHeight = Math.max(height - (isCircularChart ? 60 : 20), 300); const finalHeight = Math.max(height - (isCircularChart ? 10 : 4), 35);
console.log("🎨 ChartRenderer:", { console.log("🎨 ChartRenderer:", {
elementSubtype: element.subtype, elementSubtype: element.subtype,
@ -263,7 +263,7 @@ export function ChartRenderer({ element, data, width, height = 200 }: ChartRende
}); });
return ( return (
<div ref={containerRef} className="flex h-full w-full items-center justify-center bg-white p-2"> <div ref={containerRef} className="flex h-full w-full items-center justify-center bg-white p-0.5">
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<Chart <Chart
chartType={element.subtype} chartType={element.subtype}

View File

@ -169,7 +169,7 @@ export function PieChart({ data, config, width = 500, height = 500, isDonut = fa
.attr("x", 0) .attr("x", 0)
.attr("y", 18) .attr("y", 18)
.attr("text-anchor", "middle") // 텍스트 중앙 정렬 .attr("text-anchor", "middle") // 텍스트 중앙 정렬
.style("font-size", "10px") .style("font-size", "8px")
.style("fill", "#333") .style("fill", "#333")
.text(`${d.label} (${d.value})`); .text(`${d.label} (${d.value})`);
}); });

View File

@ -31,8 +31,8 @@ export function AnalogClock({ time, theme, timezone, customColor }: AnalogClockP
const timezoneLabel = timezone ? getTimezoneLabel(timezone) : ""; const timezoneLabel = timezone ? getTimezoneLabel(timezone) : "";
return ( return (
<div className="flex h-full flex-col items-center justify-center p-2"> <div className="flex h-full flex-col items-center justify-center p-0.5">
<svg viewBox="0 0 200 200" className="h-full max-h-[200px] w-full max-w-[200px]"> <svg viewBox="0 0 200 200" className="h-full w-full">
{/* 시계판 배경 */} {/* 시계판 배경 */}
<circle cx="100" cy="100" r="98" fill={colors.background} stroke={colors.border} strokeWidth="2" /> <circle cx="100" cy="100" r="98" fill={colors.background} stroke={colors.border} strokeWidth="2" />
@ -70,7 +70,7 @@ export function AnalogClock({ time, theme, timezone, customColor }: AnalogClockP
y={y} y={y}
textAnchor="middle" textAnchor="middle"
dominantBaseline="middle" dominantBaseline="middle"
fontSize="20" fontSize="16"
fontWeight="bold" fontWeight="bold"
fill={colors.number} fill={colors.number}
> >
@ -86,7 +86,7 @@ export function AnalogClock({ time, theme, timezone, customColor }: AnalogClockP
x2={100 + 40 * Math.cos((hourAngle * Math.PI) / 180)} x2={100 + 40 * Math.cos((hourAngle * Math.PI) / 180)}
y2={100 + 40 * Math.sin((hourAngle * Math.PI) / 180)} y2={100 + 40 * Math.sin((hourAngle * Math.PI) / 180)}
stroke={colors.hourHand} stroke={colors.hourHand}
strokeWidth="6" strokeWidth="5"
strokeLinecap="round" strokeLinecap="round"
/> />
@ -97,7 +97,7 @@ export function AnalogClock({ time, theme, timezone, customColor }: AnalogClockP
x2={100 + 60 * Math.cos((minuteAngle * Math.PI) / 180)} x2={100 + 60 * Math.cos((minuteAngle * Math.PI) / 180)}
y2={100 + 60 * Math.sin((minuteAngle * Math.PI) / 180)} y2={100 + 60 * Math.sin((minuteAngle * Math.PI) / 180)}
stroke={colors.minuteHand} stroke={colors.minuteHand}
strokeWidth="4" strokeWidth="3"
strokeLinecap="round" strokeLinecap="round"
/> />
@ -108,18 +108,18 @@ export function AnalogClock({ time, theme, timezone, customColor }: AnalogClockP
x2={100 + 75 * Math.cos((secondAngle * Math.PI) / 180)} x2={100 + 75 * Math.cos((secondAngle * Math.PI) / 180)}
y2={100 + 75 * Math.sin((secondAngle * Math.PI) / 180)} y2={100 + 75 * Math.sin((secondAngle * Math.PI) / 180)}
stroke={colors.secondHand} stroke={colors.secondHand}
strokeWidth="2" strokeWidth="1.5"
strokeLinecap="round" strokeLinecap="round"
/> />
{/* 중심점 */} {/* 중심점 */}
<circle cx="100" cy="100" r="6" fill={colors.center} /> <circle cx="100" cy="100" r="4" fill={colors.center} />
<circle cx="100" cy="100" r="3" fill={colors.background} /> <circle cx="100" cy="100" r="2" fill={colors.background} />
</svg> </svg>
{/* 타임존 표시 */} {/* 타임존 표시 */}
{timezoneLabel && ( {timezoneLabel && (
<div className="mt-1 text-center text-xs font-medium" style={{ color: colors.number }}> <div className="mt-0 text-center text-[8px] font-medium" style={{ color: colors.number }}>
{timezoneLabel} {timezoneLabel}
</div> </div>
)} )}

View File

@ -56,21 +56,21 @@ export function DigitalClock({
return ( return (
<div <div
className={`flex h-full flex-col items-center justify-center ${compact ? "p-1" : "p-4"} text-center ${themeClasses.container}`} className={`flex h-full flex-col items-center justify-center ${compact ? "p-0.5" : "p-2"} text-center ${themeClasses.container}`}
style={themeClasses.style} style={themeClasses.style}
> >
{/* 날짜 표시 (compact 모드에서는 숨김) */} {/* 날짜 표시 (compact 모드에서는 숨김) */}
{!compact && showDate && dateString && ( {!compact && showDate && dateString && (
<div className={`mb-3 text-sm font-medium ${themeClasses.date}`}>{dateString}</div> <div className={`mb-1 text-[10px] leading-tight font-medium ${themeClasses.date}`}>{dateString}</div>
)} )}
{/* 시간 표시 */} {/* 시간 표시 */}
<div className={`font-bold tabular-nums ${themeClasses.time} ${compact ? "text-xl" : "text-5xl"}`}> <div className={`leading-none font-bold tabular-nums ${themeClasses.time} ${compact ? "text-sm" : "text-2xl"}`}>
{timeString} {timeString}
</div> </div>
{/* 타임존 표시 */} {/* 타임존 표시 */}
<div className={`${compact ? "mt-0.5" : "mt-3"} text-xs font-medium ${themeClasses.timezone}`}> <div className={`${compact ? "mt-0" : "mt-1"} text-[9px] font-medium ${themeClasses.timezone}`}>
{timezoneLabel} {timezoneLabel}
</div> </div>
</div> </div>

View File

@ -374,9 +374,9 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
} }
return ( return (
<div className="flex h-full w-full items-center justify-center overflow-hidden bg-white p-2"> <div className="flex h-full w-full items-center justify-center overflow-hidden bg-white p-1">
{/* 콘텐츠 영역 - 스크롤 없이 자동으로 크기 조정 */} {/* 콘텐츠 영역 - 스크롤 없이 자동으로 크기 조정 */}
<div className="grid h-full w-full gap-2" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))" }}> <div className="grid h-full w-full gap-1" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(35px, 1fr))" }}>
{/* 그룹별 카드 (활성화 시) */} {/* 그룹별 카드 (활성화 시) */}
{isGroupByMode && {isGroupByMode &&
groupedCards.map((card, index) => { groupedCards.map((card, index) => {
@ -388,10 +388,12 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
return ( return (
<div <div
key={`group-${index}`} key={`group-${index}`}
className={`flex flex-col items-center justify-center rounded-lg border ${colors.bg} ${colors.border} p-2`} className={`flex flex-col items-center justify-center rounded border ${colors.bg} ${colors.border} p-0.5`}
> >
<div className="text-[10px] text-gray-600">{card.label}</div> <div className="text-[8px] leading-tight text-gray-600">{card.label}</div>
<div className={`mt-0.5 text-xl font-bold ${colors.text}`}>{card.value.toLocaleString()}</div> <div className={`mt-0 text-xs leading-none font-bold ${colors.text}`}>
{card.value.toLocaleString()}
</div>
</div> </div>
); );
})} })}
@ -404,12 +406,12 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
return ( return (
<div <div
key={metric.id} key={metric.id}
className={`flex flex-col items-center justify-center rounded-lg border ${colors.bg} ${colors.border} p-2`} className={`flex flex-col items-center justify-center rounded border ${colors.bg} ${colors.border} p-0.5`}
> >
<div className="text-[10px] text-gray-600">{metric.label}</div> <div className="text-[8px] leading-tight text-gray-600">{metric.label}</div>
<div className={`mt-0.5 text-xl font-bold ${colors.text}`}> <div className={`mt-0 text-xs leading-none font-bold ${colors.text}`}>
{formattedValue} {formattedValue}
<span className="ml-0.5 text-sm">{metric.unit}</span> <span className="ml-0 text-[8px]">{metric.unit}</span>
</div> </div>
</div> </div>
); );