140 lines
5.9 KiB
TypeScript
140 lines
5.9 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import React, { useState, useEffect } from "react";
|
||
|
|
import { ConfigPanelProps } from "@/lib/registry/types";
|
||
|
|
|
||
|
|
export const ButtonConfigPanel: React.FC<ConfigPanelProps> = ({ config: initialConfig, onConfigChange }) => {
|
||
|
|
const [localConfig, setLocalConfig] = useState({
|
||
|
|
label: "버튼",
|
||
|
|
text: "",
|
||
|
|
tooltip: "",
|
||
|
|
variant: "primary",
|
||
|
|
size: "medium",
|
||
|
|
disabled: false,
|
||
|
|
fullWidth: false,
|
||
|
|
...initialConfig,
|
||
|
|
});
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
setLocalConfig({
|
||
|
|
label: "버튼",
|
||
|
|
text: "",
|
||
|
|
tooltip: "",
|
||
|
|
variant: "primary",
|
||
|
|
size: "medium",
|
||
|
|
disabled: false,
|
||
|
|
fullWidth: false,
|
||
|
|
...initialConfig,
|
||
|
|
});
|
||
|
|
}, [initialConfig]);
|
||
|
|
|
||
|
|
const updateConfig = (key: string, value: any) => {
|
||
|
|
const newConfig = { ...localConfig, [key]: value };
|
||
|
|
setLocalConfig(newConfig);
|
||
|
|
onConfigChange(newConfig);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="space-y-4">
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div>
|
||
|
|
<label htmlFor="button-label" className="mb-1 block text-sm font-medium text-gray-700">
|
||
|
|
버튼 텍스트
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
id="button-label"
|
||
|
|
type="text"
|
||
|
|
value={localConfig.label || ""}
|
||
|
|
onChange={(e) => updateConfig("label", e.target.value)}
|
||
|
|
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||
|
|
placeholder="버튼에 표시될 텍스트"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label htmlFor="button-tooltip" className="mb-1 block text-sm font-medium text-gray-700">
|
||
|
|
툴팁 (선택사항)
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
id="button-tooltip"
|
||
|
|
type="text"
|
||
|
|
value={localConfig.tooltip || ""}
|
||
|
|
onChange={(e) => updateConfig("tooltip", e.target.value)}
|
||
|
|
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||
|
|
placeholder="마우스 오버 시 표시될 텍스트"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label htmlFor="button-variant" className="mb-1 block text-sm font-medium text-gray-700">
|
||
|
|
버튼 스타일
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="button-variant"
|
||
|
|
value={localConfig.variant || "primary"}
|
||
|
|
onChange={(e) => updateConfig("variant", e.target.value)}
|
||
|
|
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||
|
|
>
|
||
|
|
<option value="primary">기본 (파란색)</option>
|
||
|
|
<option value="secondary">보조 (회색)</option>
|
||
|
|
<option value="success">성공 (녹색)</option>
|
||
|
|
<option value="warning">경고 (노란색)</option>
|
||
|
|
<option value="danger">위험 (빨간색)</option>
|
||
|
|
<option value="outline">외곽선</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label htmlFor="button-size" className="mb-1 block text-sm font-medium text-gray-700">
|
||
|
|
버튼 크기
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="button-size"
|
||
|
|
value={localConfig.size || "medium"}
|
||
|
|
onChange={(e) => updateConfig("size", e.target.value)}
|
||
|
|
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||
|
|
>
|
||
|
|
<option value="small">작음</option>
|
||
|
|
<option value="medium">보통</option>
|
||
|
|
<option value="large">큼</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex items-center space-x-4">
|
||
|
|
<label className="flex items-center space-x-2">
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
checked={localConfig.disabled || false}
|
||
|
|
onChange={(e) => updateConfig("disabled", e.target.checked)}
|
||
|
|
className="border-input bg-background text-primary focus:ring-ring h-4 w-4 rounded border focus:ring-2 focus:ring-offset-2"
|
||
|
|
/>
|
||
|
|
<span className="text-sm font-medium text-gray-700">비활성화</span>
|
||
|
|
</label>
|
||
|
|
|
||
|
|
<label className="flex items-center space-x-2">
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
checked={localConfig.fullWidth || false}
|
||
|
|
onChange={(e) => updateConfig("fullWidth", e.target.checked)}
|
||
|
|
className="border-input bg-background text-primary focus:ring-ring h-4 w-4 rounded border focus:ring-2 focus:ring-offset-2"
|
||
|
|
/>
|
||
|
|
<span className="text-sm font-medium text-gray-700">전체 너비</span>
|
||
|
|
</label>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="border-t border-gray-200 pt-3">
|
||
|
|
<h4 className="mb-2 text-sm font-medium text-gray-700">미리보기</h4>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
disabled={localConfig.disabled}
|
||
|
|
className={`rounded-md px-4 py-2 text-sm font-medium transition-colors duration-200 ${localConfig.size === "small" ? "px-3 py-1 text-xs" : ""} ${localConfig.size === "large" ? "px-6 py-3 text-base" : ""} ${localConfig.variant === "primary" ? "bg-blue-600 text-white hover:bg-blue-700" : ""} ${localConfig.variant === "secondary" ? "bg-gray-600 text-white hover:bg-gray-700" : ""} ${localConfig.variant === "success" ? "bg-green-600 text-white hover:bg-green-700" : ""} ${localConfig.variant === "warning" ? "bg-yellow-600 text-white hover:bg-yellow-700" : ""} ${localConfig.variant === "danger" ? "bg-red-600 text-white hover:bg-red-700" : ""} ${localConfig.variant === "outline" ? "border border-gray-300 bg-white text-gray-700 hover:bg-gray-50" : ""} ${localConfig.fullWidth ? "w-full" : ""} ${localConfig.disabled ? "cursor-not-allowed opacity-50" : ""} `}
|
||
|
|
title={localConfig.tooltip}
|
||
|
|
>
|
||
|
|
{localConfig.label || "버튼"}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|