{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "field-wrapper", "type": "registry:component", "title": "Field Wrapper", "description": "Wrapper component for form fields providing consistent layout with labels, error messages, and helper text", "dependencies": [ "react", "@registry/react" ], "registryDependencies": [ "https://components.thgaltitude.com/r/react/alert" ], "files": [ { "path": "registry/react/component/field-wrapper.tsx", "content": "import React, { useState, Children, cloneElement, isValidElement } from \"react\";\nimport Alert from \"@registry/react/ui/alert\";\n\ninterface FieldProps {\n id?: string;\n name?: string;\n label?: string;\n helperText?: string;\n errorMessage?: string;\n placeholder?: string;\n required?: boolean;\n \"aria-invalid\"?: boolean;\n disabled?: boolean;\n maxlength?: number;\n}\n\ninterface FieldWrapperProps extends FieldProps {\n children: React.ReactNode;\n}\n\nconst FieldWrapper: React.FC = ({\n id,\n name,\n label,\n helperText,\n errorMessage,\n placeholder,\n required = false,\n \"aria-invalid\": ariaInvalid = false,\n disabled = false,\n maxlength,\n children,\n ...restProps\n}) => {\n const [inputLength, setInputLength] = useState(0);\n\n const childWithProps = React.Children.map(children, (child) => {\n if (isValidElement(child)) {\n const commonProps: any = {\n id,\n name,\n placeholder,\n disabled,\n required,\n \"aria-invalid\": ariaInvalid,\n };\n\n if (helperText && !ariaInvalid) {\n commonProps[\"aria-describedby\"] = `${id}-helper`;\n }\n\n if (maxlength) {\n commonProps.maxLength = maxlength;\n }\n\n if (maxlength) {\n commonProps.onChange = (\n e: React.ChangeEvent\n ) => {\n setInputLength(e.target.value.length);\n\n const originalOnChange = (child as any).props.onChange;\n if (typeof originalOnChange === \"function\") {\n originalOnChange(e);\n }\n };\n }\n\n const childProps = { ...(child.props as object) };\n\n return cloneElement(child, {\n ...commonProps,\n ...childProps,\n ...(maxlength ? { onChange: commonProps.onChange } : {}),\n });\n }\n return child;\n });\n\n return (\n \n
\n
\n \n {required && (\n \n Required\n \n )}\n {!required && (\n \n Optional\n \n )}\n
\n {maxlength && (\n \n {inputLength}/{maxlength}\n \n )}\n
\n
{childWithProps}
\n
\n {!ariaInvalid && helperText && (\n

\n {helperText}\n

\n )}\n {ariaInvalid && (\n \n )}\n
\n \n );\n};\n\nexport type { FieldProps };\nexport default FieldWrapper;\n", "type": "registry:component", "target": "react/component/field-wrapper.tsx" } ] }