Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 97 lines 2.9 kB view raw
1import type { ComponentProps, ReactNode } from "react"; 2import { forwardRef, memo, useId } from "react"; 3import cn from "@/helpers/cn"; 4import { FieldError } from "./Form"; 5import HelpTooltip from "./HelpTooltip"; 6 7interface InputProps extends Omit<ComponentProps<"input">, "prefix"> { 8 className?: string; 9 error?: boolean; 10 helper?: ReactNode; 11 hideError?: boolean; 12 iconLeft?: ReactNode; 13 iconRight?: ReactNode; 14 label?: ReactNode; 15 prefix?: ReactNode | string; 16} 17 18const Input = forwardRef<HTMLInputElement, InputProps>( 19 ( 20 { 21 className = "", 22 error, 23 helper, 24 hideError = false, 25 iconLeft, 26 iconRight, 27 label, 28 prefix, 29 type = "text", 30 ...props 31 }, 32 ref 33 ) => { 34 const id = useId(); 35 36 const iconStyles = [ 37 "text-zinc-500 [&>*]:peer-focus:text-gray-500 [&>*]:h-5", 38 { "!text-red-500 [&>*]:peer-focus:!text-red-500": error } 39 ]; 40 41 return ( 42 <label className="w-full" htmlFor={id}> 43 {label ? ( 44 <div className="mb-1 flex items-center space-x-1.5"> 45 <div className="font-medium text-gray-800 dark:text-gray-200"> 46 {label} 47 </div> 48 <HelpTooltip>{helper}</HelpTooltip> 49 </div> 50 ) : null} 51 <div className="flex"> 52 {prefix ? ( 53 <span className="inline-flex items-center rounded-l-xl border border-gray-300 border-r-0 bg-gray-100 px-3 text-gray-500 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-200"> 54 {prefix} 55 </span> 56 ) : null} 57 <div 58 className={cn( 59 { "!bg-gray-500/20 opacity-50": props.disabled }, 60 { "!border-red-500": error }, 61 prefix ? "rounded-r-xl" : "rounded-xl", 62 "flex w-full items-center border border-gray-300 bg-white focus-within:border-gray-500 dark:border-gray-700 dark:bg-gray-900" 63 )} 64 > 65 <input 66 className={cn( 67 { "placeholder:text-red-500": error }, 68 prefix ? "rounded-r-xl" : "rounded-xl", 69 "peer w-full border-none bg-transparent outline-hidden focus:ring-0", 70 className 71 )} 72 id={id} 73 ref={ref} 74 type={type} 75 {...props} 76 /> 77 <span 78 className={cn({ "order-first pl-3": iconLeft }, iconStyles)} 79 tabIndex={-1} 80 > 81 {iconLeft} 82 </span> 83 <span 84 className={cn({ "order-last pr-3": iconRight }, iconStyles)} 85 tabIndex={-1} 86 > 87 {iconRight} 88 </span> 89 </div> 90 </div> 91 {!hideError && props.name ? <FieldError name={props.name} /> : null} 92 </label> 93 ); 94 } 95); 96 97export default memo(Input);