@weareconceptstudio/cs-admin
Version:
A comprehensive React-based admin panel system with dynamic actions, form components, and design system
1,133 lines (966 loc) • 34.8 kB
Markdown
This document provides comprehensive documentation for all form components available in CS Admin UI.
- [FormContainer](
- [InputField](
- [SelectField](
- [Editor](
- [MediaPicker](
- [DateTimePicker](
- [ArrayField](
- [ColorField](
- [ColorPicker](
- [SlugField](
- [TreeSelectField](
- [MetaInputs](
---
The main form wrapper component that provides layout, validation, and form management.
| Prop | Type | Default | Description |
| -------------------- | ---------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `className` | string | `''` | Additional CSS classes |
| `layoutClassName` | string | `''` | Layout CSS classes |
| `initialValues` | object | `{}` | Form initial values |
| `onFinish` | function | `null` | Form submission handler |
| `onChange` | function | `null` | Form values change handler |
| `hasLayout` | boolean | `false` | Enable form layout with header and sidebar |
| `title` | string | `''` | Form title |
| `subtitle` | string/component | `null` | Form subtitle |
| `trans` | boolean | `true` | Enable translation support |
| `rightBar` | array | `[]` | Right sidebar components |
| `preview` | component | `undefined` | Preview component |
| `hasMeta` | boolean | `true` | Enable SEO meta fields |
| `hasInformation` | object | `{createdAt: true, published: false, lastModified: true, orderDate: false, sendingDate: false}` | Information panel configuration |
| `draftStatusKey` | string | `'status'` | Draft status field name |
| `hasStatusSelection` | boolean | `false` | Enable status selection |
| `statusSelection` | array/object | `null` | Status selection options |
| `buttons` | object | `{save: true, draft: false, cancel: false, delete: false}` | Button configuration |
| `additionalButtons` | component | `false` | Additional custom buttons |
| `tabs` | component | `null` | Tab navigation component |
| `hasBackButton` | boolean | `true` | Show back button |
```jsx
import { FormContainer, InputField } from '@weareconceptstudio/cs-admin';
const MyForm = ({ action, current, onFinish }) => {
return (
<FormContainer
title='Create Post'
subtitle='Fill in the details below'
hasLayout={true}
onFinish={onFinish}
initialValues={current}
buttons={{
save: true,
draft: true,
cancel: true,
delete: false,
}}
hasInformation={{
createdAt: true,
lastModified: true,
published: true,
orderDate: false,
sendingDate: false,
}}
hasBackButton={true}
hasStatusSelection={true}
statusSelection={[
{ value: 'draft', label: 'Draft' },
{ value: 'published', label: 'Published' },
{ value: 'archived', label: 'Archived' },
]}>
<InputField
name='title'
label='Title'
required={true}
/>
</FormContainer>
);
};
```
```jsx
const AdvancedForm = ({ action, current, onFinish }) => {
return (
<FormContainer
title='Advanced Post Editor'
subtitle={
<div>
<p>Create and manage your content</p>
<Badge
status='processing'
text='Auto-save enabled'
/>
</div>
}
hasLayout={true}
layoutClassName='full-width'
onFinish={onFinish}
onChange={(changedValues, allValues, form) => {
// Handle form changes
console.log('Form changed:', changedValues);
}}
initialValues={current}
trans={true}
hasBackButton={true}
buttons={{
save: { title: 'Save Changes' },
draft: true,
cancel: true,
delete: action === 'edit',
}}
additionalButtons={
<Button
type='mini'
iconName='preview'>
Preview
</Button>
}
hasInformation={{
createdAt: true,
published: true,
lastModified: true,
orderDate: false,
sendingDate: true,
}}
hasStatusSelection={true}
statusSelection={[
{ value: 'draft', label: 'Draft' },
{ value: 'review', label: 'Under Review' },
{ value: 'published', label: 'Published' },
{ value: 'archived', label: 'Archived' },
]}
draftStatusKey='status'
hasMeta={true}
rightBar={[<CustomSidebarComponent key='custom' />]}
tabs={
<Tabs
defaultActiveKey='content'
items={[
{ key: 'content', label: 'Content', children: <ContentTab /> },
{ key: 'settings', label: 'Settings', children: <SettingsTab /> },
{ key: 'seo', label: 'SEO', children: <SEOTab /> },
]}
/>
}>
{/* Form content */}
</FormContainer>
);
};
```
- **`hasLayout`**: Enables the full form layout with header, sidebar, and structured content area
- **`layoutClassName`**: Additional CSS classes for the layout container
- **`hasBackButton`**: Shows a back button in the layout header (uses context navigation)
#### Form Behavior Props
- **`onChange`**: Callback function triggered when form values change
```jsx
onChange={(changedValues, allValues, form) => {
// Handle form changes
console.log('Changed:', changedValues);
console.log('All values:', allValues);
}}
```
- **`hasInformation`**: Object controlling which information fields to show
```jsx
hasInformation={{
createdAt: true, // Show creation date
published: true, // Show published date with edit capability
lastModified: true, // Show last modified date
orderDate: false, // Show order date
sendingDate: false, // Show sending date
}}
```
- **`hasStatusSelection`**: Enable status selection in the information panel
- **`statusSelection`**: Array or object defining status options
```jsx
// Array format
statusSelection={[
{ value: 'draft', label: 'Draft' },
{ value: 'published', label: 'Published' },
]}
// Object format
statusSelection={{
draft: 'Draft',
published: 'Published',
archived: 'Archived'
}}
```
- **`draftStatusKey`**: Field name for draft status (default: 'status')
#### Button Configuration
- **`buttons`**: Object controlling form buttons
```jsx
buttons={{
save: true, // Show save button
save: { title: 'Custom Save' }, // Custom save button text
draft: true, // Show draft/publish buttons
cancel: true, // Show cancel button
delete: true, // Show delete button (edit mode)
}}
```
- **`additionalButtons`**: Custom buttons to add to the button area
- **`tabs`**: Tab navigation component for organizing form content
- **`rightBar`**: Array of components to display in the right sidebar
- **`trans`**: Enable translation support and language switcher
---
A versatile input component that supports multiple input types.
| Prop | Type | Default | Description |
| -------------- | ---------------- | --------- | ------------------------------------------------------------------------- |
| `type` | string | `'input'` | Input type: 'input', 'textarea', 'number', 'search', 'checkbox', 'switch' |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `className` | string | `''` | Additional CSS classes |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `inputOptions` | object | `{}` | Input component props |
| `maxLength` | string/number | `null` | Maximum character length |
| `allowClear` | boolean | `false` | Show clear button |
| `errorKey` | string | - | Custom error message key |
| `placeholder` | string | - | Input placeholder |
| `addonBefore` | string/component | - | Input prefix |
| `extra` | string/component | - | Extra information below field |
| `tooltip` | string/component | - | Tooltip content |
| `checkboxText` | string | - | Checkbox label text |
| `inputConfig` | object | - | Input configuration (from context) |
### Usage
```jsx
// Basic text input
<InputField
name="title"
label="Title"
placeholder="Enter title"
required={true}
maxLength={100}
/>
// Textarea
<InputField
type="textarea"
name="description"
label="Description"
maxLength="p1" // Uses config character count
autoSize={{ minRows: 4, maxRows: 10 }}
/>
// Number input
<InputField
type="number"
name="price"
label="Price"
addonBefore="$"
inputOptions={{
min: 0,
step: 0.01
}}
/>
// Search input
<InputField
type="search"
name="search"
label="Search"
onSearch={(value) => console.log(value)}
/>
// Checkbox
<InputField
type="checkbox"
name="published"
checkboxText="Published"
required={false}
/>
// Switch
<InputField
type="switch"
name="active"
label="Active"
required={false}
/>
```
---
A dropdown selection component with support for single and multiple selection.
| Prop | Type | Default | Description |
| --------------- | --------- | ------- | ----------------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `mode` | string | `null` | Selection mode: 'multiple', 'tags' |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `inputOptions` | object | `{}` | Select component props |
| `optGroup` | boolean | `false` | Enable option grouping |
| `optionKey` | string | `null` | Key for option label (defaults to 'name') |
| `optionValue` | string | `null` | Key for option value (defaults to 'id') |
| `list` | array | `[]` | Options array |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
| `placeholder` | string | `''` | Placeholder text |
| `suffixIcon` | component | - | Custom suffix icon |
| `hasBorder` | boolean | `false` | Show border |
| `className` | string | `''` | Additional CSS classes |
| `showSearch` | boolean | `false` | Enable search functionality |
| `onSelect` | function | - | Selection handler |
| `errorKey` | string | - | Custom error message key |
| `dropdownAlign` | object | - | Dropdown alignment |
### Usage
```jsx
// Basic select
<SelectField
name="category"
label="Category"
list={categories}
placeholder="Select category"
required={true}
/>
// Multiple selection
<SelectField
name="tags"
label="Tags"
mode="multiple"
list={tags}
placeholder="Select tags"
showSearch={true}
/>
// With custom option keys
<SelectField
name="status"
label="Status"
list={statuses}
optionKey="label"
optionValue="value"
required={true}
/>
// With option groups
<SelectField
name="location"
label="Location"
optGroup={true}
list={{
"North America": [
{ id: 1, name: "United States" },
{ id: 2, name: "Canada" }
],
"Europe": [
{ id: 3, name: "United Kingdom" },
{ id: 4, name: "Germany" }
]
}}
/>
```
---
A rich text editor component based on CKEditor 5.
| Prop | Type | Default | Description |
| ---------------- | ------- | ------- | -------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `toolbar` | array | `null` | Custom toolbar configuration |
| `dynamic` | boolean | `false` | Enable dynamic naming |
| `dynamicName` | string | `''` | Dynamic field name |
| `errorKey` | string | - | Custom error message key |
| `hasImageUpload` | boolean | `false` | Enable image upload |
```jsx
// Basic editor
<Editor
name="content"
label="Content"
required={true}
/>
// With custom toolbar
<Editor
name="description"
label="Description"
toolbar={[
'heading', 'bold', 'italic', 'link',
'bulletedList', 'numberedList', 'blockQuote'
]}
/>
// With image upload
<Editor
name="article"
label="Article"
hasImageUpload={true}
toolbar={[
'heading', 'bold', 'italic', 'link',
'uploadImage', 'insertTable'
]}
/>
```
---
A file upload and media selection component.
| Prop | Type | Default | Description |
| ---------------- | ------- | ----------------- | ----------------------------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `rules` | array | `[]` | Validation rules |
| `required` | boolean | `true` | Whether field is required |
| `acceptTypes` | array | `defaultAllTypes` | Accepted file types |
| `multiple` | boolean | `false` | Allow multiple file selection |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `dynamic` | boolean | `false` | Enable dynamic naming |
| `dynamicName` | string | `''` | Dynamic field name |
| `errorKey` | string | - | Custom error message key |
| `allowDimension` | object | - | Required dimensions `{width: number, height: number}` |
```jsx
// Single image upload
<MediaPicker
name="featured_image"
label="Featured Image"
acceptTypes={['image/*']}
required={true}
/>
// Multiple files
<MediaPicker
name="gallery"
label="Gallery"
acceptTypes={['image/*', 'video/*']}
multiple={true}
required={false}
/>
// With dimension requirements
<MediaPicker
name="banner"
label="Banner Image"
acceptTypes={['image/*']}
allowDimension={{ width: 1200, height: 630 }}
required={true}
/>
// Document upload
<MediaPicker
name="document"
label="Document"
acceptTypes={['application/pdf', 'application/msword']}
required={true}
/>
```
---
A date and time selection component with multiple picker types.
| Prop | Type | Default | Description |
| --------------- | --------- | --------------- | ------------------------------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `inputOptions` | object | `{}` | Picker component props |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
| `type` | string | `'date'` | Picker type: 'date', 'time', 'date-range', 'time-range' |
| `format` | string | `'DD/MM/YYYY'` | Display format |
| `outputFormat` | string | `''` | Output format (uses format if empty) |
| `className` | string | `'date-picker'` | Additional CSS classes |
| `suffixIcon` | component | `null` | Custom suffix icon |
| `multiple` | boolean | `false` | Allow multiple date selection |
| `errorKey` | string | - | Custom error message key |
| `inputReadOnly` | boolean | `false` | Make input read-only |
### Usage
```jsx
// Date picker
<DateTimePicker
name="publish_date"
label="Publish Date"
type="date"
format="DD/MM/YYYY"
required={true}
/>
// Time picker
<DateTimePicker
name="event_time"
label="Event Time"
type="time"
format="HH:mm"
required={true}
/>
// Date range picker
<DateTimePicker
name="date_range"
label="Date Range"
type="date-range"
format="DD/MM/YYYY"
required={true}
/>
// Time range picker
<DateTimePicker
name="time_range"
label="Time Range"
type="time-range"
format="HH:mm"
required={true}
/>
// With custom format
<DateTimePicker
name="created_at"
label="Created At"
type="date"
format="YYYY-MM-DD"
outputFormat="YYYY-MM-DD HH:mm:ss"
required={true}
/>
```
---
A dynamic array field component for managing lists of data.
| Prop | Type | Default | Description |
| ------------- | -------- | -------- | ---------------------------------- |
| `fullPrefix` | array | - | Full field path prefix |
| `prefix` | string | - | Field prefix |
| `isRequired` | boolean | `true` | Whether field is required |
| `renderItem` | function | - | Function to render each array item |
| `btnText` | string | `'item'` | Add button text |
| `btnProps` | object | `{}` | Add button props |
| `hideButton` | boolean | `false` | Hide add button |
| `addOptions` | object | `{}` | Default values for new items |
| `draggable` | boolean | `false` | Enable drag-and-drop reordering |
| `collapsable` | boolean | `true` | Enable collapsible items |
| `max` | number | - | Maximum number of items |
```jsx
// Basic array field
<ArrayField
prefix="features"
isRequired={true}
btnText="Add Feature"
renderItem={(field, index, remove) => (
<div key={field.key}>
<InputField
{...field}
name={[field.name, 'title']}
label="Feature Title"
/>
<InputField
{...field}
name={[field.name, 'description']}
label="Description"
type="textarea"
/>
<Button onClick={() => remove(field.name)}>Remove</Button>
</div>
)}
/>
// Draggable array field
<ArrayField
prefix="steps"
draggable={true}
btnText="Add Step"
renderItem={(field, index, remove) => (
<div key={field.key}>
<InputField
{...field}
name={[field.name, 'step']}
label={`Step ${index + 1}`}
/>
</div>
)}
/>
// With maximum items
<ArrayField
prefix="tags"
max={5}
btnText="Add Tag"
renderItem={(field, index, remove) => (
<InputField
{...field}
name={[field.name, 'name']}
label="Tag Name"
/>
)}
/>
```
---
A color selection component with predefined color options.
| Prop | Type | Default | Description |
| -------------- | -------- | --------- | ---------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `mode` | string | `null` | Selection mode: 'multiple', 'tags' |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `inputOptions` | object | `{}` | Select component props |
| `optionKey` | string | `'id'` | Key for option value |
| `optionValue` | string | `'value'` | Key for color value |
| `optionTitle` | string | `'name'` | Key for option label |
| `list` | array | `[]` | Color options array |
| `placeholder` | string | `''` | Placeholder text |
| `errorKey` | string | - | Custom error message key |
| `onSelect` | function | - | Selection handler |
```jsx
// Basic color field
<ColorField
name="primary_color"
label="Primary Color"
list={[
{ id: 1, name: 'Red', value: '#ff0000' },
{ id: 2, name: 'Blue', value: '#0000ff' },
{ id: 3, name: 'Green', value: '#00ff00' }
]}
required={true}
/>
// Multiple color selection
<ColorField
name="theme_colors"
label="Theme Colors"
mode="multiple"
list={colorPalette}
required={false}
/>
```
---
A color picker component with visual color selection.
| Prop | Type | Default | Description |
| -------------- | ------- | ------- | -------------------------------- |
| `label` | string | `''` | Field label |
| `name` | string | `''` | Field name |
| `rules` | array | `[]` | Validation rules |
| `required` | boolean | `true` | Whether field is required |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `dynamic` | boolean | `false` | Enable dynamic naming |
| `dynamicName` | string | `''` | Dynamic field name |
| `errorKey` | string | - | Custom error message key |
```jsx
// Basic color picker
<ColorPicker
name="background_color"
label="Background Color"
required={true}
/>
// Optional color picker
<ColorPicker
name="accent_color"
label="Accent Color"
required={false}
/>
```
---
A slug generation field that automatically creates URL-friendly slugs from another field.
| Prop | Type | Default | Description |
| ----------------- | ------ | ------- | ---------------------------------------------------------- |
| `listener` | string | - | **Required** - Field name to listen to for slug generation |
| `table` | string | - | **Required** - Table name for slug validation |
| `defaultLanguage` | string | - | Default language (from context) |
| `languages` | array | - | Available languages (from context) |
### Usage
```jsx
// Basic slug field
<SlugField
listener="title"
table="posts"
/>
// With translation support
<SlugField
listener="title"
table="articles"
/>
```
---
A hierarchical selection component for tree-structured data.
| Prop | Type | Default | Description |
| -------------- | ------- | ---------------------------------------------------- | -------------------------------- |
| `label` | string | - | Field label |
| `name` | string | - | Field name |
| `labelOptions` | object | `{}` | Ant Design Form.Item label props |
| `fieldNames` | object | `{label: 'name', value: 'id', children: 'children'}` | Field name mapping |
| `list` | array | `[]` | Tree data array |
| `inputOptions` | object | `{}` | TreeSelect component props |
| `required` | boolean | `true` | Whether field is required |
| `rules` | array | `[]` | Validation rules |
```jsx
// Basic tree select
<TreeSelectField
name="category"
label="Category"
list={categoryTree}
required={true}
/>
// With custom field names
<TreeSelectField
name="department"
label="Department"
list={departmentTree}
fieldNames={{
label: 'title',
value: 'code',
children: 'subdepartments'
}}
required={true}
/>
```
---
A predefined component for SEO meta fields (title, description, image).
### Props
This component has no props as it provides a standard set of SEO fields.
### Usage
```jsx
// Basic meta inputs
<MetaInputs />
// The component automatically provides:
// - Meta Title (max 60 characters)
// - Meta Description (max 160 characters)
// - Meta Image (1200x630px recommended)
```
---
## Form Validation
All form components support Ant Design's validation system. Here are common validation patterns:
### Basic Validation
```jsx
<InputField
name='email'
label='Email'
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Please enter a valid email' },
]}
/>
```
```jsx
<InputField
name='password'
label='Password'
rules={[
{ required: true, message: 'Password is required' },
{ min: 8, message: 'Password must be at least 8 characters' },
{
validator: (_, value) => {
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
return Promise.reject(new Error('Password must contain uppercase, lowercase, and number'));
}
return Promise.resolve();
},
},
]}
/>
```
```jsx
<InputField
name='phone'
label='Phone'
rules={[
{
validator: (_, value) => {
if (form.getFieldValue('contact_method') === 'phone' && !value) {
return Promise.reject(new Error('Phone is required when contact method is phone'));
}
return Promise.resolve();
},
},
]}
/>
```
---
```jsx
<FormContainer
title='Create Post'
hasLayout={true}
onFinish={handleSubmit}>
<InputField
name='title'
label='Title'
/>
<Editor
name='content'
label='Content'
/>
<MediaPicker
name='image'
label='Featured Image'
/>
</FormContainer>
```
```jsx
<FormContainer
title='Edit Post'
hasLayout={true}
rightBar={[<CustomComponent key='custom' />]}
hasInformation={{
createdAt: true,
lastModified: true,
}}>
{/* Form fields */}
</FormContainer>
```
```jsx
<FormContainer
title='Product'
hasLayout={true}
tabs={
<Tabs
items={[
{ key: 'general', label: 'General', children: <GeneralTab /> },
{ key: 'seo', label: 'SEO', children: <SEOTab /> },
]}
/>
}>
{/* Form content */}
</FormContainer>
```
---
1. **Always provide meaningful labels** for accessibility
2. **Use appropriate validation rules** for data integrity
3. **Group related fields** using containers or collapsible sections
4. **Provide helpful placeholder text** for better UX
5. **Use required fields sparingly** - only mark truly essential fields
6. **Test form validation** with various input scenarios
7. **Consider mobile responsiveness** when designing forms
8. **Use consistent field naming** conventions
9. **Provide clear error messages** that help users fix issues
10. **Consider form performance** with large datasets
---
```jsx
import {
FormContainer,
InputField,
SelectField,
Editor,
MediaPicker,
DateTimePicker,
ArrayField,
ColorPicker,
MetaInputs,
} from '@weareconceptstudio/cs-admin';
const PostForm = ({ action, current, onFinish }) => {
return (
<FormContainer
title={action === 'create' ? 'Create Post' : 'Edit Post'}
hasLayout={true}
onFinish={onFinish}
initialValues={current}
buttons={{
save: true,
draft: true,
cancel: true,
}}
hasInformation={{
createdAt: true,
lastModified: true,
}}>
{/* Basic Information */}
<InputField
name='title'
label='Title'
placeholder='Enter post title'
required={true}
maxLength={100}
/>
<InputField
type='textarea'
name='excerpt'
label='Excerpt'
maxLength='p1'
placeholder='Brief description of the post'
/>
<Editor
name='content'
label='Content'
hasImageUpload={true}
required={true}
/>
{/* Media */}
<MediaPicker
name='featured_image'
label='Featured Image'
acceptTypes={['image/*']}
allowDimension={{ width: 1200, height: 630 }}
required={true}
/>
<MediaPicker
name='gallery'
label='Gallery'
acceptTypes={['image/*']}
multiple={true}
required={false}
/>
{/* Categorization */}
<SelectField
name='category'
label='Category'
list={categories}
placeholder='Select category'
required={true}
/>
<SelectField
name='tags'
label='Tags'
mode='multiple'
list={tags}
placeholder='Select tags'
showSearch={true}
/>
{/* Publishing */}
<DateTimePicker
name='publish_date'
label='Publish Date'
type='date'
format='DD/MM/YYYY'
required={true}
/>
<InputField
type='switch'
name='featured'
label='Featured Post'
required={false}
/>
{/* Custom Fields */}
<ArrayField
prefix='custom_fields'
btnText='Add Custom Field'
renderItem={(field, index, remove) => (
<div
key={field.key}
style={{ display: 'flex', gap: '10px', marginBottom: '10px' }}>
<InputField
{...field}
name={[field.name, 'key']}
label='Field Key'
placeholder='e.g., price'
/>
<InputField
{...field}
name={[field.name, 'value']}
label='Field Value'
placeholder='e.g., $29.99'
/>
<Button onClick={() => remove(field.name)}>Remove</Button>
</div>
)}
/>
{/* SEO */}
<MetaInputs />
</FormContainer>
);
};
```
This documentation covers all the form components available in CS Admin UI. Each component is designed to be flexible and integrate seamlessly with the overall admin system.