{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "float-label",
  "title": "Float Label",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/float-label/FloatLabel.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface FloatLabelProps extends React.HTMLAttributes<HTMLDivElement> {\n  label: string\n  required?: boolean\n  disabled?: boolean\n}\n\nconst FloatLabel = React.forwardRef<HTMLDivElement, FloatLabelProps>(\n  ({ label, required = false, disabled = false, className, children, ...props }, ref) => {\n    const wrapperRef = React.useRef<HTMLDivElement | null>(null)\n    const [isFocused, setIsFocused] = React.useState(false)\n    const [hasValue, setHasValue] = React.useState(false)\n\n    const isFloating = isFocused || hasValue\n\n    const setRefs = React.useCallback(\n      (node: HTMLDivElement | null) => {\n        wrapperRef.current = node\n        if (typeof ref === 'function') ref(node)\n        else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n      },\n      [ref],\n    )\n\n    function checkValue(target: EventTarget | null) {\n      const el = target as HTMLElement | null\n      if (!el) return\n      if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {\n        setHasValue(!!el.value)\n      } else {\n        const input = el.querySelector?.('input, textarea, select') as\n          | HTMLInputElement\n          | HTMLTextAreaElement\n          | HTMLSelectElement\n          | null\n        if (input) setHasValue(!!input.value)\n      }\n    }\n\n    // Check for prefilled value on mount (before any focus/input events fire).\n    React.useLayoutEffect(() => {\n      const wrapper = wrapperRef.current\n      if (!wrapper) return\n      const input = wrapper.querySelector('input, textarea, select') as\n        | HTMLInputElement\n        | HTMLTextAreaElement\n        | HTMLSelectElement\n        | null\n      if (input) setHasValue(!!input.value)\n    }, [])\n\n    function handleFocusIn(event: React.FocusEvent<HTMLDivElement>) {\n      setIsFocused(true)\n      checkValue(event.target)\n    }\n\n    function handleFocusOut(event: React.FocusEvent<HTMLDivElement>) {\n      setIsFocused(false)\n      checkValue(event.target)\n    }\n\n    function handleInput(event: React.FormEvent<HTMLDivElement>) {\n      checkValue(event.target)\n    }\n\n    const wrapperClasses = cn(\n      'relative flex flex-col',\n      disabled && 'opacity-50 cursor-not-allowed',\n      className,\n    )\n\n    const labelClasses = cn(\n      'text-muted-foreground pointer-events-none absolute left-3 z-10 bg-transparent px-1 text-sm transition-all duration-200',\n      !isFloating && 'top-1/2 -translate-y-1/2',\n      isFloating && 'top-0 -translate-y-1/2 scale-75 bg-background text-foreground',\n      isFocused && 'text-ring',\n      required && \"after:text-destructive after:ml-0.5 after:content-['*']\",\n    )\n\n    return (\n      <div\n        ref={setRefs}\n        className={wrapperClasses}\n        data-uipkge=\"\"\n        data-slot=\"float-label\"\n        data-floating={isFloating}\n        onFocus={handleFocusIn}\n        onBlur={handleFocusOut}\n        onInput={handleInput}\n        onChange={handleInput}\n        {...props}\n      >\n        <label className={labelClasses}>{label}</label>\n        {children}\n      </div>\n    )\n  },\n)\nFloatLabel.displayName = 'FloatLabel'\n\nexport { FloatLabel }\n",
      "type": "registry:ui",
      "target": "~/components/ui/float-label/FloatLabel.tsx"
    },
    {
      "path": "packages/registry-react/components/float-label/index.ts",
      "content": "export { FloatLabel, type FloatLabelProps } from './FloatLabel'\n",
      "type": "registry:ui",
      "target": "~/components/ui/float-label/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Floating label wrapper for any input element. The label floats up when the input is focused or has a value. Wrap it around any input, select, or textarea. Supports required indicator and disabled state.",
  "categories": [
    "control",
    "form"
  ]
}