@xcelsior/ui-fields
v1.0.5
Published
A React component library that provides form field components integrated with react-hook-form, built on top of the @xcelsior/design-system package.
Readme
@xcelsior/ui-fields
A React component library that provides form field components integrated with react-hook-form, built on top of the @xcelsior/design-system package.
Installation
npm install @xcelsior/ui-fieldsPeer Dependencies
This package requires the following peer dependencies:
react>= 19react-dom>= 19@xcelsior/design-system(workspace package)
Components
TextInputField
A text input field component integrated with react-hook-form.
import { TextInputField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<TextInputField
control={control}
name="email"
label="Email"
type="email"
required
rules={{
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address'
}
}}
/>
);
};SelectField
A select field component integrated with react-hook-form.
import { SelectField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<SelectField
control={control}
name="country"
label="Country"
required
options={[
{ value: 'AU', label: 'Australia' },
{ value: 'VN', label: 'Vietnam' }
]}
rules={{
required: 'Country is required'
}}
/>
);
};CheckboxField
A checkbox field component integrated with react-hook-form.
import { CheckboxField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<CheckboxField
control={control}
name="acceptTerms"
label="Accept Terms and Conditions"
required
rules={{
required: 'You must accept the terms and conditions'
}}
/>
);
};DatePickerField
A date picker field component integrated with react-hook-form.
import { DatePickerField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<DatePickerField
control={control}
name="birthDate"
label="Birth Date"
placeholder="Select your birth date"
required
dateFormat="dd-MM-yyyy"
rules={{
required: 'Birth date is required'
}}
/>
);
};TimePickerField
A time picker field component integrated with react-hook-form.
import { TimePickerField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<TimePickerField
control={control}
name="startTime"
label="Start Time"
placeholder="Select start time"
required
format12Hour={true}
rules={{
required: 'Start time is required'
}}
/>
);
};DateTimePickerField
A combined date and time picker field component integrated with react-hook-form.
import { DateTimePickerField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<DateTimePickerField
control={control}
name="eventDateTime"
label="Event Date & Time"
datePlaceholder="Select date"
timePlaceholder="Select time"
required
outputFormat="iso"
dateFormat="dd-MM-yyyy"
format12Hour={true}
rules={{
required: 'Event date and time is required'
}}
/>
);
};AddressFormField
A comprehensive address form field component with country-specific formatting (Australia and Vietnam).
import { AddressFormField } from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
const MyForm = () => {
const { control } = useForm();
return (
<AddressFormField
control={control}
name="address"
country="AU"
required
t={(key) => translations[key] || key}
showAutoComplete={false}
initialAddressesList={[
{ id: '1', addressLine: '123 Main St, Sydney, NSW 2000' },
{ id: '2', addressLine: '456 Queen St, Melbourne, VIC 3000' }
]}
onSelectExistingAddress={(id) => {
// Handle existing address selection
console.log('Selected address:', id);
}}
/>
);
};AddressFormField Props
| Prop | Type | Description |
|------|------|-------------|
| name | string | The name prefix for the address fields |
| control | Control | The react-hook-form control object |
| country | 'AU' \| 'VN' | The country for address formatting |
| required | boolean | Whether the fields are required (default: true) |
| t | (key: string) => string | Translation function |
| showAutoComplete | boolean | Whether to show the auto-complete address field |
| initialAddressesList | Array<{id: string, addressLine: string}> | List of existing addresses |
| onSelectExistingAddress | (id: string) => void | Callback when an existing address is selected |
| containerClassName | string | Custom className for the container |
| labelClassName | string | Custom className for labels |
Address Data Structure
The AddressFormField creates the following nested structure in your form:
interface AddressData {
areaLevel1?: string; // State/Province
areaLevel2?: string; // Suburb/District
areaLevel3?: string; // Ward (VN only)
streetAddress?: string; // Street address
postcode?: string; // Postcode (AU only)
addressLine?: string; // Auto-generated full address
autoAddress?: string; // Auto-complete input (optional)
existAddress?: string; // Selected existing address ID (optional)
}Features
- Full react-hook-form integration: All components use
useControllerfor proper integration - TypeScript support: Fully typed with generics for form data
- Country-specific formatting: Address fields adapt to AU/VN formats
- Auto-generated address line: Automatically builds full address from components
- Validation support: Built-in error handling and validation rules
- Consistent styling: Based on @xcelsior/design-system components
- Accessibility: Proper ARIA attributes and keyboard navigation
Complete Form Example
Here's a comprehensive example showing how to use all the field components together:
import {
TextInputField,
TextAreaField,
SelectField,
CheckboxField,
DatePickerField,
TimePickerField,
DateTimePickerField
} from '@xcelsior/ui-fields';
import { useForm } from 'react-hook-form';
interface FormData {
name: string;
email: string;
country: string;
description: string;
acceptTerms: boolean;
birthDate: string;
meetingTime: string;
eventDateTime: string;
}
const ComprehensiveForm = () => {
const { control, handleSubmit } = useForm<FormData>();
const onSubmit = (data: FormData) => {
console.log('Form submitted:', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<TextInputField
control={control}
name="name"
label="Full Name"
placeholder="Enter your full name"
required
rules={{ required: 'Name is required' }}
/>
<TextInputField
control={control}
name="email"
label="Email Address"
type="email"
placeholder="Enter your email"
required
rules={{
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address'
}
}}
/>
<SelectField
control={control}
name="country"
label="Country"
required
options={[
{ value: 'AU', label: 'Australia' },
{ value: 'VN', label: 'Vietnam' }
]}
rules={{ required: 'Country is required' }}
/>
<DatePickerField
control={control}
name="birthDate"
label="Birth Date"
placeholder="Select your birth date"
required
dateFormat="dd-MM-yyyy"
rules={{ required: 'Birth date is required' }}
/>
<TimePickerField
control={control}
name="meetingTime"
label="Preferred Meeting Time"
placeholder="Select time"
format12Hour={true}
rules={{ required: 'Meeting time is required' }}
/>
<DateTimePickerField
control={control}
name="eventDateTime"
label="Event Date & Time"
datePlaceholder="Select date"
timePlaceholder="Select time"
required
outputFormat="iso"
dateFormat="dd-MM-yyyy"
format12Hour={true}
rules={{ required: 'Event date and time is required' }}
/>
<TextAreaField
control={control}
name="description"
label="Additional Notes"
placeholder="Any additional information..."
rows={3}
/>
<CheckboxField
control={control}
name="acceptTerms"
label="I accept the terms and conditions"
required
rules={{ required: 'You must accept the terms and conditions' }}
/>
<button type="submit" className="px-4 py-2 bg-blue-600 text-white rounded">
Submit Form
</button>
</form>
);
};Best Practices
- Use consistent naming: Follow the memory preference to use 'product' instead of 'unified' in component names
- Provide validation rules: Always include appropriate validation for required fields
- Use TypeScript: Leverage the TypeScript support for better developer experience
- Handle translations: Provide translation functions for international applications
- Consider accessibility: Test with screen readers and keyboard navigation
- Date/Time formats: Choose appropriate date formats and time formats for your use case
- Timezone handling: Use ISO format for DateTimePickerField when dealing with server data
Development
# Build the package
npm run build
# Build in watch mode
npm run dev
# Type check
npm run type-check
# Lint
npm run lintLicense
Private package - not for public distribution.
