Files
rustfs-console/components/copy-input.tsx
T
2026-06-15 14:09:15 +08:00

70 lines
1.7 KiB
TypeScript

"use client"
import * as React from "react"
import { useTranslation } from "react-i18next"
import { RiFileCopyLine } from "@remixicon/react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { copyToClipboard } from "@/lib/clipboard"
import { useMessage } from "@/lib/feedback/message"
import { cn } from "@/lib/utils"
interface CopyInputProps extends Omit<React.ComponentProps<typeof Input>, "value" | "onChange"> {
value?: string
onChange?: (value: string) => void
readonly?: boolean
copyIcon?: boolean
className?: string
}
export function CopyInput({
value = "",
onChange,
readonly = false,
copyIcon = false,
className,
...props
}: CopyInputProps) {
const { t } = useTranslation()
const message = useMessage()
const handleCopy = async () => {
try {
await copyToClipboard(value)
message.success(t("Copy Success"))
} catch {
message.error(t("Copy Failed"))
}
}
return (
<div className={cn("flex h-full items-center gap-2", className)}>
<Input
value={value}
onChange={(e) => onChange?.(e.target.value)}
readOnly={readonly}
aria-label={props["aria-label"] ?? t("Copy")}
className="flex-1"
{...props}
/>
{!copyIcon ? (
<Button type="button" variant="default" onClick={handleCopy}>
{t("Copy")}
</Button>
) : (
<Button
type="button"
variant="ghost"
size="sm"
className="shrink-0 outline"
title={t("Copy")}
onClick={handleCopy}
>
<RiFileCopyLine className="size-4" aria-hidden />
<span className="sr-only">{t("Copy")}</span>
</Button>
)}
</div>
)
}