{"name":"email-input","title":"EmailInput","type":"registry:ui","files":[{"path":"src/components/ui/email-input.tsx","type":"registry:ui","target":"@ui/email-input.tsx","content":"\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"./lib/utils\";\n\nexport interface EmailInputProps {\n  value?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  validate?: boolean;\n  className?: string;\n}\n\nconst SUGGESTION_DOMAINS = [\n  { domain: \"gmail.com\", suggestion: \"DID YOU MEAN\" },\n  { domain: \"yahoo.com\", suggestion: \"DID YOU MEAN\" },\n  { domain: \"outlook.com\", suggestion: \"DID YOU MEAN\" },\n];\n\nconst validateEmail = (email: string) => {\n  const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  return re.test(email);\n};\n\nexport function EmailInput({\n  value: controlledValue,\n  defaultValue = \"\",\n  onValueChange,\n  validate = true,\n  className,\n}: EmailInputProps) {\n  const [internalValue, setInternalValue] = React.useState(defaultValue);\n  const [touched, setTouched] = React.useState(false);\n  const [error, setError] = React.useState(false);\n  const [showSuggestion, setShowSuggestion] = React.useState(false);\n  const [suggestionDomain, setSuggestionDomain] = React.useState(\"\");\n\n  const isControlled = controlledValue !== undefined;\n  const currentValue = isControlled ? controlledValue : internalValue;\n\n  React.useEffect(() => {\n    if (isControlled) {\n      setInternalValue(controlledValue);\n      setError(false);\n      setTouched(false);\n      setShowSuggestion(false);\n    }\n  }, [isControlled, controlledValue]);\n\n  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = e.target.value;\n    setInternalValue(val);\n    setError(false);\n    setShowSuggestion(false);\n    onValueChange?.(val);\n  };\n\n  const handleBlur = () => {\n    setTouched(true);\n    if (validate && !validateEmail(currentValue)) {\n      setError(true);\n    }\n  };\n\n  const detectDomain = () => {\n    const match = currentValue.match(/@([a-zA-Z0-9.-]+)$/);\n    if (match) {\n      const domain = match[1];\n      const suggestion = SUGGESTION_DOMAINS.find((s) => s.domain === domain);\n      if (suggestion) {\n        setSuggestionDomain(suggestion.domain);\n        setShowSuggestion(true);\n      } else {\n        setShowSuggestion(false);\n      }\n    } else {\n      setShowSuggestion(false);\n    }\n  };\n\n  React.useEffect(detectDomain, [currentValue]);\n\n  const classes = cn(\n    \"relative rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm transition-colors\",\n    \"ring-2 ring-ring focus-visible:outline-none focus-visible:ring-2\",\n    className,\n  );\n\n  const errorClasses = cn(\n    \"ring-1 ring-destructive/50\",\n    error && \"placeholder-destructive\",\n    !error && \"\",\n  );\n\n  return (\n    <div className={cn(\"space-y-1.5\", className)}>\n      <input\n        type=\"email\"\n        value={currentValue}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        className={classes}\n        disabled={validate && error}\n        aria-invalid={error || undefined}\n        aria-describedby={error ? \"email-error\" : undefined}\n      />\n      {error && (\n        <p id=\"email-error\" className=\"text-[10px] uppercase tracking-[0.15em] text-destructive\">\n          Please enter a valid email address\n        </p>\n      )}\n      {showSuggestion && !error && (\n        <div\n          onMouseLeave={() => setShowSuggestion(false)}\n          className=\"absolute right-2 top-full mt-1 rounded-md bg-secondary p-1.5 shadow-xs text-[10px] uppercase tracking-[0.15em] text-secondary-foreground animate-[slide-in_0.2s_ease-out_both] z-20\"\n        >\n          <span className=\"font-mono me-1\">@</span>\n          <span className=\"font-medium\">{suggestionDomain}</span>\n        </div>\n      )}\n    </div>\n  );\n}\n\nEmailInput.displayName = \"EmailInput\";\n\n"}],"registryDependencies":["https://ui.bigbullapp.com/r/utils.json"]}