{
  "name": "tsf-password-field",
  "type": "registry:ui",
  "dependencies": [
    "lucide-react",
    "react"
  ],
  "registryDependencies": [
    "field",
    "input-group",
    "tooltip",
    "tsf-form-context"
  ],
  "files": [
    {
      "path": "./items/tanstack-form/password-field/component.tsx",
      "type": "registry:ui",
      "target": "./components/ui/shuip/tanstack-form/password-field.tsx",
      "content": "'use client';\n\nimport { Eye, EyeOff, InfoIcon } from 'lucide-react';\nimport React from 'react';\nimport { Field, FieldDescription, FieldError, FieldLabel } from '@/components/ui/field';\nimport { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from '@/components/ui/input-group';\nimport { useFieldContext } from '@/components/ui/shuip/tanstack-form/form-context';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\n\nexport interface PasswordFieldProps {\n  label?: string;\n  description?: string;\n  fieldProps?: React.ComponentProps<typeof Field>;\n  props?: React.ComponentProps<'input'>;\n  tooltip?: React.ReactNode;\n}\n\nexport function PasswordField({ label, description, fieldProps, props, tooltip }: PasswordFieldProps) {\n  const field = useFieldContext<string>();\n  const { isValid, errors } = field.state.meta;\n  const [showPassword, setShowPassword] = React.useState(false);\n\n  const handleTogglePassword = React.useCallback(() => {\n    setShowPassword((prev) => !prev);\n  }, []);\n\n  return (\n    <Field className='gap-2' data-invalid={!isValid} {...fieldProps}>\n      {label && <FieldLabel htmlFor={field.name}>{label}</FieldLabel>}\n      <InputGroup>\n        <InputGroupInput\n          id={field.name}\n          type={showPassword ? 'text' : 'password'}\n          placeholder='Enter password'\n          name={field.name}\n          value={field.state.value}\n          onChange={(e) => field.handleChange(e.target.value)}\n          onBlur={field.handleBlur}\n          aria-invalid={!isValid}\n          {...props}\n        />\n        <InputGroupAddon align='inline-end'>\n          <InputGroupButton aria-label='Toggle password' onClick={handleTogglePassword}>\n            {showPassword ? <EyeOff className='size-4' /> : <Eye className='size-4' />}\n          </InputGroupButton>\n          {tooltip && (\n            <Tooltip>\n              <TooltipTrigger asChild>\n                <InputGroupButton aria-label='Info' size='icon-xs'>\n                  <InfoIcon />\n                </InputGroupButton>\n              </TooltipTrigger>\n              <TooltipContent>{tooltip}</TooltipContent>\n            </Tooltip>\n          )}\n        </InputGroupAddon>\n      </InputGroup>\n      {!isValid && (\n        <FieldError\n          className='text-xs text-left'\n          errors={errors.map((error) => ({ message: typeof error === 'string' ? error : error?.message }))}\n        />\n      )}\n      {description && <FieldDescription className='text-xs'>{description}</FieldDescription>}\n    </Field>\n  );\n}\n"
    }
  ],
  "$schema": "https://ui.shadcn.com/schema/registry-item.json"
}
