You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.2 KiB
72 lines
2.2 KiB
import * as React from "react";
|
|
|
|
import { cn } from "@core/utils/cn.ts";
|
|
import { type VariantProps, cva } from "class-variance-authority";
|
|
import type { LucideIcon } from "lucide-react";
|
|
|
|
const inputVariants = cva(
|
|
"flex h-10 w-full rounded-md border bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-hidden focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
|
|
{
|
|
variants: {
|
|
variant: {
|
|
default: "border-slate-300 dark:border-slate-700",
|
|
invalid: "border-red-500 dark:border-red-500",
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
variant: "default",
|
|
},
|
|
},
|
|
);
|
|
|
|
export interface InputProps
|
|
extends React.InputHTMLAttributes<HTMLInputElement>,
|
|
VariantProps<typeof inputVariants> {
|
|
prefix?: string;
|
|
suffix?: string;
|
|
action?: {
|
|
icon: LucideIcon;
|
|
onClick: () => void;
|
|
};
|
|
}
|
|
|
|
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
({ className, value, variant, prefix, suffix, action, ...props }, ref) => {
|
|
return (
|
|
<div className="relative w-full">
|
|
{prefix && (
|
|
<span className="inline-flex items-center rounded-l-md bg-gray-100/90 px-3 font-mono text-sm text-slate-600">
|
|
{prefix}
|
|
</span>
|
|
)}
|
|
<input
|
|
className={cn(
|
|
action && "pr-8",
|
|
inputVariants({ variant }),
|
|
className,
|
|
)}
|
|
value={value}
|
|
ref={ref}
|
|
{...props}
|
|
/>
|
|
{suffix && (
|
|
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-9 font-mono text-slate-500">
|
|
<span className="text-gray-100/40 sm:text-sm">{suffix}</span>
|
|
</div>
|
|
)}
|
|
{action && (
|
|
<button
|
|
type="button"
|
|
className="absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500 hover:text-gray-400 focus:outline-hidden "
|
|
onClick={action.onClick}
|
|
>
|
|
<action.icon size={20} />
|
|
</button>
|
|
)}
|
|
</div>
|
|
);
|
|
},
|
|
);
|
|
Input.displayName = "Input";
|
|
|
|
export { Input, inputVariants };
|
|
|