import React from 'react'; import { type ResolvedFieldPresentation, resolveFieldPresentation, resolveFieldState, } from '../../../../../internal/resolvers'; import type { FieldProps } from '../../../../../types/field'; import { View } from '../../../../layout/public'; import { Text } from '../../../../typography/public'; /*** Composes a control with its label and helper or error message. */ export function Field({ children, label, helperText, errorText, required = false, disabled = false, invalid = false, readOnly = false, testID, }: FieldProps) { const hasErrorText = Boolean(errorText); const presentation = resolveFieldPresentation( resolveFieldState({ disabled, invalid: invalid || hasErrorText, readOnly }), ); const message = hasErrorText ? errorText : helperText; return ( {renderFieldLabel(label, required, presentation)} {children} {renderFieldMessage(message, presentation)} ); } /*** Renders an optional field label and required indicator. */ function renderFieldLabel( label: React.ReactNode, required: boolean, presentation: ResolvedFieldPresentation, ) { if (label === undefined || label === null) return null; const labelContent = typeof label === 'string' || typeof label === 'number' ? ( {label} ) : ( label ); return ( {labelContent} {required ? ( * ) : null} ); } /*** Renders an optional helper or error message using field presentation semantics. */ function renderFieldMessage(message: React.ReactNode, presentation: ResolvedFieldPresentation) { if (message === undefined || message === null || message === '') return null; if (typeof message !== 'string' && typeof message !== 'number') return message; return ( {message} ); }