rallly/packages/ui/src/text-field.tsx
2024-11-02 11:50:09 +00:00

93 lines
2.4 KiB
TypeScript

"use client";
import type { VariantProps } from "class-variance-authority";
import { cva } from "class-variance-authority";
import * as React from "react";
import type { IconProps } from "./icon";
import { Icon } from "./icon";
import { cn } from "./lib/utils";
const inputVariants = cva(
cn(
"focus:border-primary-400 focus-visible:ring-primary-100 focus-visible:ring-2",
"border-input placeholder:text-muted-foreground h-9 rounded border bg-gray-50 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:cursor-not-allowed disabled:opacity-50",
),
{
variants: {
size: {
sm: "h-7 text-xs px-1",
md: "h-9 text-sm px-2",
lg: "h-12 text-lg px-3",
},
},
defaultVariants: {
size: "md",
},
},
);
export type InputProps = Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"size"
> &
VariantProps<typeof inputVariants>;
const TextFieldInput = React.forwardRef<HTMLInputElement, InputProps>(
({ className, size, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
inputVariants({ size }),
"group-[.text-field]:border-0 group-[.text-field]:bg-transparent group-[.text-field]:p-0 group-[.text-field]:ring-0 group-[.text-field]:ring-offset-0",
className,
)}
ref={ref}
{...props}
/>
);
},
);
TextFieldInput.displayName = "TextFieldInput";
interface TextFieldProps extends InputProps {
children?: React.ReactNode;
}
const TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(
({ className, size, children, ...props }, ref) => {
return (
<div
ref={ref}
onClick={(e) => {
const target = e.target as HTMLElement;
// find an input that s a direct descendant of the target
target.querySelector("input")?.focus();
}}
className={cn(
"flex items-center",
"text-field group",
"focus-within:border-primary-400 focus-within:ring-primary-100 focus-within:ring-2",
inputVariants({ size }),
"p-0",
className,
)}
{...props}
>
{children}
</div>
);
},
);
TextField.displayName = "TextField";
function TextFieldIcon(props: IconProps) {
return (
<div className="pointer-events-none px-2">
<Icon {...props} />
</div>
);
}
export { TextField, TextFieldIcon, TextFieldInput };