Files
cc-switch/src/components/providers/forms/ApiKeyInput.tsx
T
Jason 7f86dbe299 fix(providers): show the preset's promotion under the API Key field again
The v7 visual pass dropped the partner promotion box together with the
promoted ordering. Ordering stays by name, but the promotion text comes
back as the API Key field's hint (caption, secondary text, no box), shown
only when the "Get API Key" link is shown, as before.

ApiKeyInput gains a generic `hint` prop for text below the input.
2026-10-04 12:58:31 +08:00

84 lines
2.3 KiB
TypeScript

import React, { useState } from "react";
import { Eye, EyeOff } from "lucide-react";
import { useTranslation } from "react-i18next";
import { fieldClass } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import { REQUIRED_LABEL } from "./BasicFormFields";
interface ApiKeyInputProps {
value: string;
onChange: (value: string) => void;
placeholder?: string;
disabled?: boolean;
required?: boolean;
label?: string;
id?: string;
/** 标签行右侧(「获取 API Key ↗」) */
labelAside?: React.ReactNode;
/** 输入框下方的说明文字 */
hint?: React.ReactNode;
}
const ApiKeyInput: React.FC<ApiKeyInputProps> = ({
value,
onChange,
placeholder,
disabled = false,
required = false,
label = "API Key",
id = "apiKey",
labelAside,
hint,
}) => {
const { t } = useTranslation();
const [showKey, setShowKey] = useState(false);
return (
<div className="space-y-2">
<div className="flex items-center justify-between gap-2">
<label
htmlFor={id}
className={cn(
"block text-caption font-medium text-fg-1",
required && REQUIRED_LABEL,
)}
>
{label}
</label>
{labelAside}
</div>
<div className="relative">
<input
type={showKey ? "text" : "password"}
id={id}
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder ?? t("apiKeyInput.placeholder")}
disabled={disabled}
required={required}
aria-required={required || undefined}
autoComplete="off"
className={cn(
fieldClass,
"h-8 pe-10",
disabled && "border-border bg-subtle text-fg-3 opacity-100",
)}
/>
{!disabled && value && (
<button
type="button"
onClick={() => setShowKey(!showKey)}
className="absolute inset-y-0 end-0 flex items-center pe-3 text-fg-3 transition-colors hover:text-fg-1"
aria-label={showKey ? t("apiKeyInput.hide") : t("apiKeyInput.show")}
>
{showKey ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
)}
</div>
{hint && <p className="text-caption text-fg-2">{hint}</p>}
</div>
);
};
export default ApiKeyInput;