{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "textarea",
  "title": "TextareaField",
  "description": "Textarea field for BuzzForm v2.",
  "registryDependencies": [
    "@buzzform/init",
    "textarea",
    "field",
    "@buzzform/copy"
  ],
  "files": [
    {
      "path": "registry/shadcn/fields/textarea.tsx",
      "content": "\"use client\";\n\nimport { useRef, useEffect } from \"react\";\nimport type { TextareaField as TextareaFieldDef } from \"@buildnbuzz/form-react\";\nimport { useDataField } from \"@buildnbuzz/form-react\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { CopyButton } from \"../components/copy-button\";\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldError,\n  FieldGroup,\n  FieldLabel,\n} from \"@/components/ui/field\";\nimport { cn } from \"@/lib/utils\";\n\ninterface TextareaUi {\n  autoResize?: boolean;\n  rows?: number;\n  copyable?: boolean;\n  autoFocus?: boolean;\n  className?: string;\n  width?: string | number;\n  asterisk?: boolean;\n}\n\nexport function TextareaField() {\n  const {\n    fieldApi,\n    field,\n    isDisabled,\n    isReadOnly,\n    isRequired,\n    label,\n    placeholder,\n    description,\n    errors,\n    isInvalid,\n    descriptionId,\n    errorId,\n    ariaDescribedBy,\n    handleChange,\n    handleBlur,\n  } = useDataField<TextareaFieldDef>();\n\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const value = (fieldApi.state.value as string) ?? \"\";\n  const ui = field.ui as TextareaUi | undefined;\n\n  const width = ui?.width;\n  const widthStyle = width\n    ? {\n        width: typeof width === \"number\" ? `${width}px` : width,\n        flex: \"0 1 auto\",\n      }\n    : undefined;\n\n  // Character count logic\n  const showCharCount = field.maxLength !== undefined;\n  const charCount = typeof value === \"string\" ? value.length : 0;\n  const isOverLimit = showCharCount && charCount > field.maxLength!;\n\n  // Auto-resize logic\n  useEffect(() => {\n    const textarea = textareaRef.current;\n    if (textarea && ui?.autoResize) {\n      textarea.style.height = \"auto\";\n      textarea.style.height = `${textarea.scrollHeight}px`;\n    }\n  }, [value, ui?.autoResize]);\n\n  return (\n    <FieldGroup\n      data-field={fieldApi.name}\n      className={ui?.className}\n      style={widthStyle}\n    >\n      <Field data-invalid={isInvalid || isOverLimit} data-disabled={isDisabled}>\n        {label && (\n          <FieldLabel htmlFor={fieldApi.name} className=\"gap-1 items-baseline\">\n            {label}\n            {isRequired && ui?.asterisk !== false ? (\n              <span className=\"text-destructive\">*</span>\n            ) : null}\n          </FieldLabel>\n        )}\n\n        <FieldContent>\n          <div className={cn(\"relative\", ui?.copyable && \"flex items-start\")}>\n            <Textarea\n              ref={textareaRef}\n              id={fieldApi.name}\n              name={fieldApi.name}\n              autoComplete={field.autoComplete}\n              autoFocus={ui?.autoFocus}\n              value={value}\n              onChange={(e) => handleChange(e.target.value)}\n              onBlur={handleBlur}\n              placeholder={placeholder}\n              disabled={isDisabled}\n              readOnly={isReadOnly}\n              aria-invalid={isInvalid || isOverLimit}\n              aria-describedby={ariaDescribedBy}\n              minLength={field.minLength}\n              maxLength={field.maxLength}\n              required={isRequired}\n              rows={ui?.rows ?? 3}\n              className={cn(ui?.copyable && \"pr-9\")}\n              style={\n                ui?.autoResize\n                  ? { resize: \"none\", overflow: \"hidden\" }\n                  : ({\n                      resize: \"none\",\n                      fieldSizing: \"fixed\",\n                    } as React.CSSProperties)\n              }\n            />\n            {ui?.copyable && (\n              <CopyButton\n                value={value}\n                disabled={isDisabled}\n                className=\"absolute right-0 top-0 h-9 px-2.5 text-muted-foreground hover:text-foreground\"\n              />\n            )}\n          </div>\n\n          {/* Character count */}\n          {showCharCount && (\n            <div\n              className={cn(\n                \"text-xs mt-1.5 text-right\",\n                isOverLimit ? \"text-destructive\" : \"text-muted-foreground\",\n              )}\n            >\n              {charCount} / {field.maxLength}\n            </div>\n          )}\n        </FieldContent>\n\n        {description && !isInvalid && (\n          <FieldDescription id={descriptionId}>{description}</FieldDescription>\n        )}\n\n        {isInvalid && <FieldError id={errorId} errors={errors} />}\n      </Field>\n    </FieldGroup>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/fields/textarea.tsx"
    }
  ],
  "type": "registry:ui"
}