yg-sdui-forms
v1.0.1
Published
React UI Component Library using React Hook Form
Readme
yg-sdui-forms 🚀
A lightweight, configuration-driven React form library built on top of React Hook Form. It makes forms completely configurable so that their structure, validations, and visibility rules can be managed via JSON configuration without modifying React code.
🔗 Quick Links
- NPM Package: yg-sdui-forms on npm
🧠 Server-Driven UI (SDUI)
Server-Driven UI is an architectural pattern where the server sends a JSON configuration describing which pre-built UI components should be rendered and how they should behave.
Core Architecture Layers:
- Component Library: Pre-built UI components.
- Component Mapper: Registry mapping configuration strings (
c_name) to React components. - Component Renderer: Reads the JSON configuration and instantiates the mapped components with their configured props.
⚡ State Management
Form state is divided into:
- Server State: API updates, caching, and background queries (best managed by tools like TanStack Query).
- Local State: Immediate user inputs, validations, and dynamic layouts inside forms (managed by React Hook Form).
Why React Hook Form?
- Zero Boilerplate: Uses dot-notation paths (e.g.,
accountDetail.username) to register nested objects automatically. - Performance: Minimizes unnecessary re-renders.
- Validation: Supports standard HTML validation attributes (
required,minLength,pattern, etc.).
👁️ Dynamic Visibility Rules
Define conditional visibility rules directly within the JSON configuration:
{
"c_name": "TextInput",
"path": "profile.restrictedBio",
"label": "Restricted Bio",
"visibility": "profile.age",
"value": 18
}How It Works:
- The
<FormRenderer />component checks thevisibilityandvalueproperties. - It uses
useWatchto listen to the field path specified byvisibility. - If the watched field's value equals the target
value, the component is rendered. Otherwise, it returnsnull. - Note: For backwards compatibility, the legacy nested format
Visibility: { field: "path", value: val }is also supported.
🚀 Getting Started
1. Installation
Install the package alongside react-hook-form:
npm install yg-sdui-forms react-hook-form2. Basic Setup
Wrap the form in react-hook-form's FormProvider and render fields using <FormRenderer />.
import React from 'react';
import { useForm, FormProvider } from 'react-hook-form';
import { FormRenderer } from 'yg-sdui-forms';
const formFields = [
{
c_name: 'TextInput',
path: 'accountDetail.username',
label: 'Username',
placeholder: 'Enter your username',
validation: { required: 'Username is required' }
},
{
c_name: 'EmailInput',
path: 'accountDetail.email',
label: 'Email Address',
placeholder: 'Enter your email',
validation: { required: 'Email is required' }
}
];
function MyForm() {
const methods = useForm({
defaultValues: {
accountDetail: { username: '', email: '' }
}
});
const onSubmit = (data) => {
console.log('Submitted Data:', data);
};
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
{/* Render fields dynamically */}
<FormRenderer fields={formFields} />
<button type="submit" style={submitBtnStyle}>Submit</button>
</form>
</FormProvider>
);
}
const submitBtnStyle = {
padding: '10px 20px',
backgroundColor: '#6366f1',
color: '#fff',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontWeight: '600'
};📦 Component Catalog
yg-sdui-forms includes 18 pre-styled components categorized for form data capture. Every component is designed with standard focus states, custom toggle behaviors, and validation error styling.
1. Text & Numeric Inputs
| Component Name (c_name) | Purpose / Description | Key Props / Behaviors |
| :--- | :--- | :--- |
| TextInput | General single-line input field. | placeholder, standard input props |
| Textarea | Multi-line text field. | rows (defaults to 4) |
| NumberInput | Input constraint for numbers. | min, max, step |
| EmailInput | Specialized email input field. | Auto type validation |
| PasswordInput | Secure entry with an eye toggle. | Toggle visibility button |
| PhoneInput | Country code and flag selector. | Dynamic country flag alignment |
| URLInput | Input with a prefix badge (https://). | Prefix labels |
| SearchInput | Search field with clean icon integration. | - |
2. Selection Components
| Component Name (c_name) | Purpose / Description | Config Options |
| :--- | :--- | :--- |
| Select | Dropdown single selection list. | options: [{ value, label }] |
| MultiSelect | Dropdown list returning selected items as pills. | options: [{ value, label }] |
| RadioGroup | Radio button group. | options, layout ('vertical' | 'horizontal') |
| Checkbox | Single checkbox returning boolean. | Standard checked behavior |
| CheckboxGroup | Multiple checkboxes returning string arrays. | options, layout ('vertical' | 'horizontal') |
| ToggleSwitch | iOS-style sliding boolean switch. | - |
3. Date & Time Components
| Component Name (c_name) | Purpose / Description | Key Props / Behaviors |
| :--- | :--- | :--- |
| DatePicker | Calendar dropdown selection. | Native date input |
| TimePicker | Digital clock input. | Native time input |
| DateTimePicker | Combination calendar and clock. | Native datetime-local input |
| DateRangePicker | Dual calendar selection for start/end dates. | startPath, endPath, startLabel, endLabel |
⚙️ Schema Reference
Every field item in your schema configuration array should follow this structure:
| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| c_name | string | Yes | The component name matching the registry (e.g. 'TextInput'). |
| path | string | Yes | Dot-notation nested state binding path (e.g. 'profile.bio'). Note: Excluded in DateRangePicker in favor of startPath/endPath. |
| label | string | No | Label text rendered above the field. |
| placeholder| string | No | Suggestive input help text. |
| visibility | string | No | The field path to watch for conditional visibility. |
| value | any | No | The target value for the visibility condition. If the watched field's value equals this, the field is shown. |
| validation | object | No | Hook form validators: { required, min, max, pattern, minLength, maxLength }. |
🛠️ Showcase Example
Here is a comprehensive form configuration representing a nested registration system with conditional visibility:
const userRegistrationConfig = [
{
c_name: 'TextInput',
path: 'auth.username',
label: 'Username',
placeholder: 'username',
validation: { required: 'Username is required' }
},
{
c_name: 'PasswordInput',
path: 'auth.security.password',
label: 'Account Password',
placeholder: 'Minimum 8 characters',
validation: {
required: 'Password is required',
minLength: { value: 8, message: 'Password is too short' }
}
},
{
c_name: 'NumberInput',
path: 'personal.age',
label: 'Age',
placeholder: '21',
validation: { required: 'Please specify age' }
},
{
c_name: 'Textarea',
path: 'personal.restrictedBio',
label: 'Special Bio (Only visible for 18-year-olds)',
placeholder: 'Tell us your story...',
visibility: 'personal.age',
value: 18
},
{
c_name: 'MultiSelect',
path: 'preferences.techStack',
label: 'Preferred Technologies',
options: [
{ value: 'react', label: 'React.js' },
{ value: 'node', label: 'Node.js' },
{ value: 'ts', label: 'TypeScript' },
{ value: 'rust', label: 'Rust' }
],
validation: { required: 'Choose at least one technology' }
},
{
c_name: 'DateRangePicker',
startPath: 'vacation.start',
endPath: 'vacation.end',
label: 'Scheduled Leave',
startLabel: 'Leave Starts',
endLabel: 'Leave Ends'
}
];🔌 Extending with Custom Components
Extend the library by registering custom components to componentMap:
import { componentMap, FormRenderer } from 'yg-sdui-forms';
// 1. Define custom React input
const CustomRatingInput = ({ path, label }) => {
return (
<div>
<label>{label}</label>
{/* custom register fields */}
</div>
);
};
// 2. Register it with the componentMap dictionary
componentMap['RatingInput'] = CustomRatingInput;
// 3. Use in JSON configuration
const config = [
{
c_name: 'RatingInput',
path: 'feedback.stars',
label: 'Rate your experience'
}
];