import { Undo2, X } from "lucide-react"; import { useState } from "react"; import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx"; import { Button } from "~/components/ui/button.tsx"; import { Input } from "~/components/ui/input.tsx"; import { Textarea } from "~/components/ui/textarea.tsx"; import { SECRET_CLEAR, secretView } from "~/lib/secret.ts"; import { cn } from "~/lib/utils.ts"; /** * 只写凭证输入框。已保存时框里显示掩码占位(「已设置 ••••••••」,服务端给了末 4 位就带上), * 聚焦后直接输入即替换;留空保存 = 保持原值;「清除」确认后把值设为 SECRET_CLEAR,保存时才生效。 * 值约定见 ~/lib/secret.ts。明文只在用户输入时存在于这个表单里,从不由服务端回填。 */ export function SecretInput({ id, value, onChange, isSet, mask, clearable = false, label = "凭证", placeholder, multiline = false, disabled, invalid, className, }: { id?: string; value: string; onChange: (v: string) => void; /** 服务端已保存(secretRef / hasCredential 等) */ isSet: boolean; /** 服务端给的掩码 hint(如 credentialMask),只取末 4 位显示 */ mask?: string | null; /** 允许清除(必填凭证不给) */ clearable?: boolean; /** 确认弹窗里的名字:"API Key"、"密码" */ label?: string; placeholder?: string; /** Cookie 这类长串用多行 */ multiline?: boolean; disabled?: boolean; invalid?: boolean; className?: string; }) { const [confirming, setConfirming] = useState(false); const view = secretView(value, { isSet, mask, clearable }); if (view.state === "cleared") { return (
); } const shownPlaceholder = view.state === "set" ? view.placeholder : placeholder; const common = { id, value, disabled, // 没有外部