"use client" import * as React from "react"; import { Loader2 } from "lucide-react"; import { cn } from "../../utils/cn"; import { FieldWrapper } from "./field-wrapper"; export interface InputProps extends React.InputHTMLAttributes { /** When true, renders error border & ring */ invalid?: boolean; /** Element displayed at the start (left) of the input */ startAdornment?: React.ReactNode; /** Element displayed at the end (right) of the input */ endAdornment?: React.ReactNode; /** Label text displayed above the input */ label?: string; /** Status message displayed below the input */ error?: string; /** Color variant for the message: "error" (red), "warning" (yellow), "success" (green) or "muted" (grey). Only "error" and "warning" mark the field invalid (colored border). */ errorVariant?: "error" | "warning" | "success" | "muted"; /** When true, shows a loading spinner as end adornment */ loading?: boolean; } const invalidBorderClasses = { error: "border-ods-error hover:border-ods-error has-[:focus]:border-ods-error", warning: "!border-ods-warning hover:!border-ods-warning has-[:focus]:!border-ods-warning", } as const; const Input = React.forwardRef( ({ className, type, invalid = false, startAdornment, endAdornment, label, error, errorVariant = "error", loading = false, ...props }, ref) => { // success/muted are informational — they never paint the invalid border const variantIsInvalid = errorVariant === "error" || errorVariant === "warning" const isInvalid = invalid || (!!error && variantIsInvalid) // Range inputs get a clean slider rendering — no label wrapper, borders, or adornments if (type === 'range') { const rangeInput = ( ) return label ? ( {rangeInput} ) : rangeInput } const content = ( ) return ( {content} ) } ) Input.displayName = "Input" export { Input };