@algodomain/smart-forms
v0.1.7
Published
A powerful React form framework with smart fields, multi-tab support, and seamless API integration
Downloads
727
Maintainers
Readme
@algodomain/smart-forms
A powerful, flexible React form framework with smart fields, multi-tab support, built-in validation, and seamless API integration.
Built with TypeScript, Tailwind CSS, Zod validation, and shadcn/ui components.
📋 Table of Contents
- Features
- Installation
- Quick Start
- Form Components
- Field Components
- Opinionated Fields
- Configuration Reference
- Advanced Features
- Theming
- Hooks & Context
- Examples
- Troubleshooting
- Contributing
✨ Features
- 🎯 Smart Fields - Pre-built, validated form fields with consistent UX
- 📑 Multi-Tab Forms - Create complex forms with tabbed navigation and progress tracking
- ✅ Built-in Validation - Powered by Zod for type-safe validation
- 🔄 API Integration - Automatic form submission with authentication support
- 🔗 Query Params - Include URL query parameters in form submissions
- 💾 Auto-Save - LocalStorage support for draft saving
- 🎛️ Conditional Disabling - Disable fields and submit buttons based on form data
- 🎨 Customizable - Full theme control via CSS variables
- 🌙 Dark Mode - Built-in support for light and dark themes
- ♿ Accessible - Built on Radix UI primitives
- 📦 Tree-Shakeable - Import only what you need
- 🔒 Type-Safe - Full TypeScript support
📦 Installation
1. Install the Package
npm install @algodomain/smart-forms
# or
yarn add @algodomain/smart-forms
# or
pnpm add @algodomain/smart-forms2. Install Peer Dependencies
npm install react react-dom tailwindcss zod react-toastify date-fns lucide-react3. Import Styles
Add to your main entry file (main.tsx or index.tsx):
import '@algodomain/smart-forms/style.css'
import 'react-toastify/dist/ReactToastify.css'4. Configure Tailwind CSS (v4)
Add @source directives to scan the package for Tailwind classes:
/* src/index.css */
@import "tailwindcss";
@source "../node_modules/@algodomain/smart-forms/dist/index.js";
@source "../node_modules/@algodomain/smart-forms/dist/index.cjs";
@import "@algodomain/smart-forms/style.css";🚀 Quick Start
Basic Form Example
import { SmartForm } from '@algodomain/smart-forms'
import { SmartInput, SmartSelect } from '@algodomain/smart-forms/fields'
import { FieldEmail } from '@algodomain/smart-forms/opinionated'
import { z } from 'zod'
function RegistrationForm() {
return (
<SmartForm
api="https://api.example.com/register"
method="POST"
submitButtonText="Sign Up"
onSuccess={(data) => console.log('Success!', data)}
onError={(error) => console.error('Error:', error)}
>
<SmartInput
field="name"
label="Full Name"
validation={z.string().min(3, 'Name must be at least 3 characters')}
required
/>
<FieldEmail field="email" required />
<SmartSelect
field="role"
label="Role"
options={[
{ value: 'user', label: 'User' },
{ value: 'admin', label: 'Admin' }
]}
required
/>
</SmartForm>
)
}Multi-Tab Form Example
import { MultiTabSmartForm, Tab } from '@algodomain/smart-forms'
import { SmartInput, SmartTags } from '@algodomain/smart-forms/fields'
import { z } from 'zod'
function JobPostingForm() {
return (
<MultiTabSmartForm
api="/api/jobs"
method="POST"
showProgressBar={true}
showTabNumbers={true}
onSuccess={(data) => console.log('Job created:', data)}
>
<Tab title="Basic Info">
<SmartInput
field="jobTitle"
label="Job Title"
validation={z.string().min(3)}
required
/>
</Tab>
<Tab title="Requirements">
<SmartTags
field="skills"
label="Required Skills"
validation={z.array(z.string()).min(1)}
required
/>
</Tab>
</MultiTabSmartForm>
)
}📝 Form Components
SmartForm
Single-page form with automatic submission handling.
Usage:
<SmartForm
api="/api/endpoint"
method="POST"
onSuccess={(data) => console.log(data)}
onError={(error) => console.error(error)}
>
{/* Your fields here */}
</SmartForm>MultiTabSmartForm
Multi-step form with tabs and progress tracking.
Usage:
<MultiTabSmartForm
api="/api/submit"
showProgressBar={true}
showTabNumbers={true}
>
<Tab title="Step 1">
{/* Fields */}
</Tab>
<Tab title="Step 2">
{/* Fields */}
</Tab>
</MultiTabSmartForm>BaseSmartForm
Low-level form component for custom layouts.
Usage:
<BaseSmartForm api="/api/submit">
<div className="custom-layout">
<SmartInput field="name" label="Name" />
<CustomSubmitButton />
</div>
</BaseSmartForm>🎯 Field Components
All field components are imported from @algodomain/smart-forms/fields:
import {
SmartInput,
SmartSelect,
SmartCheckbox,
SmartRadioGroup,
SmartDatePicker,
SmartTags,
SmartSlider,
SmartDualRangeSlider,
SmartCombobox,
SmartBasicRichTextbox,
SmartFileUpload,
SmartAutoSuggestTags
} from '@algodomain/smart-forms/fields'SmartInput
Text input with support for multiple types.
<SmartInput
field="username"
label="Username"
type="text"
placeholder="Enter username"
validation={z.string().min(3).max(20)}
required
/>Supported types: text, email, password, tel, number, textarea
SmartSelect
Dropdown select field.
<SmartSelect
field="country"
label="Country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' }
]}
required
/>SmartCheckbox
Checkbox with label.
<SmartCheckbox
field="terms"
label="I agree to terms"
validation={z.boolean().refine(val => val === true)}
required
/>SmartRadioGroup
Radio button group.
<SmartRadioGroup
field="gender"
label="Gender"
options={[
{ value: 'male', label: 'Male' },
{ value: 'female', label: 'Female' }
]}
alignment="horizontal"
required
/>SmartDatePicker
Date picker with calendar UI.
<SmartDatePicker
field="birthDate"
label="Date of Birth"
validation={z.date()}
required
/>SmartTags
Tag input for multiple values.
<SmartTags
field="skills"
label="Skills"
placeholder="Type and press Enter"
validation={z.array(z.string()).min(1)}
maxTags={10}
required
/>SmartSlider
Single value slider.
<SmartSlider
field="experience"
label="Years of Experience"
min={0}
max={40}
step={1}
showValue={true}
/>SmartDualRangeSlider
Min/max range slider.
<SmartDualRangeSlider
minField="minSalary"
maxField="maxSalary"
label="Salary Range"
min={0}
max={200000}
step={5000}
/>SmartCombobox
Searchable combo box.
<SmartCombobox
field="technology"
label="Technology"
options={[
{ value: 'react', label: 'React' },
{ value: 'vue', label: 'Vue' }
]}
allowCustom={true}
/>SmartBasicRichTextbox
Basic rich text editor.
<SmartBasicRichTextbox
field="description"
label="Description"
minHeight="150px"
validation={z.string().min(50)}
required
/>SmartFileUpload
File upload field.
<SmartFileUpload
field="resume"
label="Upload Resume"
accept=".pdf,.doc,.docx"
maxSize={5 * 1024 * 1024}
required
/>🎨 Opinionated Fields
Pre-configured fields with built-in validation. Import from @algodomain/smart-forms/opinionated:
import {
FieldEmail,
FieldPassword,
FieldConfirmPassword,
FieldPhone,
FieldFirstName,
FieldLastName,
FieldFullName,
FieldAge,
FieldStreetAddress,
FieldCity,
FieldState,
FieldZipCode,
FieldMessage,
FieldComments
} from '@algodomain/smart-forms/opinionated'Usage:
<FieldEmail field="email" required />
<FieldPassword field="password" required />
<FieldPhone field="phone" />
<FieldFullName field="fullName" required />⚙️ Configuration Reference
Form Component Props
All form components (SmartForm, MultiTabSmartForm, BaseSmartForm) support these props:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| api | string | - | API endpoint for form submission |
| method | 'POST' \| 'PUT' \| 'PATCH' | 'POST' | HTTP method |
| submitButtonText | string | 'Submit' | Submit button text |
| submitButtonIcon | ReactNode | - | Icon for submit button |
| allowSaveDraft | boolean | false | Enable draft saving |
| saveDraftApi | string | - | API endpoint for saving drafts |
| enableLocalStorage | boolean | false | Save drafts to localStorage |
| storageKey | string | 'smart-form-data' | Key for localStorage |
| logFormData | boolean | false | Log form data to console |
| onSuccess | (data: unknown) => void | - | Success callback |
| onError | (error: unknown) => void | - | Error callback |
| transformData | (data: any) => any | - | Transform data before submission |
| className | string | 'max-w-2xl mx-auto p-6 bg-white' | Container CSS class |
| title | string | - | Form title |
| subTitle | string | - | Form subtitle |
| logo | ReactNode | - | Logo to display |
| footer | ReactNode | - | Footer content |
| initialData | Record<string, unknown> | {} | Initial form values |
| showReset | boolean | false | Show reset button |
| showProgressBar | boolean | true | Display progress bar (MultiTab only) |
| showTabNumbers | boolean | true | Show tab numbers (MultiTab only) |
| authentication | AuthenticationConfig | - | Authentication configuration |
| includeQueryParams | boolean | false | Include URL query parameters |
| queryParamsToInclude | string[] | - | Filter specific query params |
| submitDisabled | boolean \| ((formData: any) => boolean) | false | Disable submit button statically or conditionally based on form data |
| children | ReactNode | - | Form content |
Authentication Configuration
interface AuthenticationConfig {
enable: boolean // Enable authentication
refreshTokenEndpoint?: string // Token refresh endpoint
accessTokenKey?: string // localStorage key (default: 'accessToken')
refreshTokenKey?: string // localStorage key (default: 'refreshToken')
}Usage:
<SmartForm
authentication={{
enable: true,
refreshTokenEndpoint: "/api/auth/refresh",
accessTokenKey: "accessToken",
refreshTokenKey: "refreshToken"
}}
>
{/* Fields */}
</SmartForm>Common Field Props
All field components support these props:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| field | string | - | Required. Field identifier |
| label | string | - | Field label |
| required | boolean | false | Mark as required |
| validation | ZodSchema | - | Zod validation schema |
| defaultValue | any | - | Initial value |
| placeholder | string | - | Placeholder text |
| className | string | - | Custom CSS class |
| info | string | - | Info tooltip text |
| subLabel | string | - | Additional helper text |
| disabled | boolean \| ((formData: any) => boolean) | false | Disable field statically or conditionally based on form data |
| hidden | boolean \| ((formData: any) => boolean) | false | Hide field conditionally based on form data |
Field-Specific Props
SmartInput
| Prop | Type | Default | Allowed Values |
|------|------|---------|----------------|
| type | string | 'text' | text, email, password, tel, number, textarea |
SmartSelect / SmartCombobox
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| options | Array<{value: string, label: string}> | [] | Select options |
| allowCustom | boolean | false | Allow custom values (Combobox only) |
SmartRadioGroup
| Prop | Type | Default | Allowed Values |
|------|------|---------|----------------|
| options | Array<{value: string, label: string}> | [] | Radio options |
| alignment | string | 'vertical' | horizontal, vertical |
SmartTags
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| maxTags | number | - | Maximum number of tags |
| maxLength | number | - | Max length per tag |
| minLength | number | - | Min length per tag |
| allowDuplicates | boolean | true | Allow duplicate tags |
SmartSlider
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| min | number | 0 | Minimum value |
| max | number | 100 | Maximum value |
| step | number | 1 | Step increment |
| showValue | boolean | true | Display current value |
| valueFormatter | (value: number) => string | - | Format displayed value |
SmartDualRangeSlider
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| minField | string | - | Required. Field name for min value |
| maxField | string | - | Required. Field name for max value |
| min | number | 0 | Minimum value |
| max | number | 100 | Maximum value |
| step | number | 1 | Step increment |
| showValues | boolean | true | Display values |
| valueFormatter | (value: number) => string | - | Format displayed value |
SmartBasicRichTextbox
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| minHeight | string | '150px' | Minimum height |
| maxHeight | string | '400px' | Maximum height |
SmartFileUpload
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| accept | string | - | Accepted file types |
| maxSize | number | - | Max file size in bytes |
🚀 Advanced Features
Conditional Field Disabling
Disable fields or submit buttons based on form data values. Supports both static boolean values and dynamic functions.
Disable Fields Conditionally
Static Disable:
<SmartInput
field="username"
label="Username"
disabled={true}
/>Conditional Disable Based on Form Data:
<SmartForm api="/api/submit">
<SmartCombobox
field="country"
label="Country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' }
]}
placeholder="Please select the country"
/>
<SmartCombobox
field="state"
label="State"
options={stateOptions}
disabled={(formData) => !formData.country || formData.country === ""}
/>
<SmartInput
field="zipCode"
label="Zip Code"
disabled={(formData) => !formData.state}
/>
</SmartForm>How it works:
- The
disabledfunction receives the currentformDataobject - It re-evaluates automatically when form data changes
- Returns
trueto disable,falseto enable - Empty strings,
null, andundefinedare all falsy in JavaScript
Example: Disable until checkbox is checked:
<SmartForm api="/api/submit">
<SmartCheckbox
field="agreeToTerms"
label="I agree to the terms and conditions"
/>
<SmartInput
field="comments"
label="Additional Comments"
disabled={(formData) => !formData.agreeToTerms}
/>
</SmartForm>Example: Complex conditional logic:
<SmartInput
field="phone"
label="Phone Number"
disabled={(formData) => {
// Disable if email is not provided OR if user is under 18
return !formData.email || (formData.age && formData.age < 18)
}}
/>Disable Submit Button Conditionally
Static Disable:
<SmartForm
api="/api/submit"
submitDisabled={true}
>
{/* Fields */}
</SmartForm>Conditional Disable:
<SmartForm
api="/api/submit"
submitDisabled={(formData) => !formData.agreeToTerms}
>
<SmartInput field="name" label="Name" required />
<SmartCheckbox
field="agreeToTerms"
label="I agree to the terms"
/>
</SmartForm>Example: Disable submit until all required fields are filled:
<SmartForm
api="/api/submit"
submitDisabled={(formData) => {
return !formData.name || !formData.email || !formData.agreeToTerms
}}
>
<SmartInput field="name" label="Name" required />
<SmartInput field="email" label="Email" required />
<SmartCheckbox field="agreeToTerms" label="I agree" required />
</SmartForm>Note: The submit button is automatically disabled when isLoading is true. The submitDisabled prop is combined with the loading state: disabled={isLoading || isSubmitDisabled}.
Combining Disabled and Hidden
You can use both disabled and hidden together for different scenarios:
<SmartForm api="/api/submit">
<SmartSelect
field="userType"
label="User Type"
options={[
{ value: 'admin', label: 'Admin' },
{ value: 'user', label: 'User' }
]}
/>
{/* Hidden for non-admin users */}
<SmartInput
field="adminCode"
label="Admin Code"
hidden={(formData) => formData.userType !== 'admin'}
/>
{/* Disabled (but visible) for admin users */}
<SmartInput
field="userNotes"
label="User Notes"
disabled={(formData) => formData.userType === 'admin'}
/>
</SmartForm>Hide Fields Conditionally
Hide fields completely from the form based on form data. When a field is hidden, it's not rendered at all (unlike disabled which shows the field but makes it non-interactive).
Static Hide:
<SmartInput
field="optionalField"
label="Optional Field"
hidden={true}
/>Conditional Hide:
<SmartForm api="/api/submit">
<SmartSelect
field="accountType"
label="Account Type"
options={[
{ value: 'personal', label: 'Personal' },
{ value: 'business', label: 'Business' }
]}
/>
{/* Only show business fields when account type is business */}
<SmartInput
field="businessName"
label="Business Name"
hidden={(formData) => formData.accountType !== 'business'}
/>
<SmartInput
field="taxId"
label="Tax ID"
hidden={(formData) => formData.accountType !== 'business'}
/>
</SmartForm>Example: Show/hide based on checkbox:
<SmartForm api="/api/submit">
<SmartCheckbox
field="hasSpecialRequirements"
label="I have special requirements"
/>
<SmartInput
field="specialRequirements"
label="Please describe your requirements"
type="textarea"
hidden={(formData) => !formData.hasSpecialRequirements}
/>
</SmartForm>Difference between disabled and hidden:
disabled: Field is visible but grayed out and non-interactivehidden: Field is completely removed from the DOM (not rendered)
When to use each:
- Use
disabledwhen you want to show the field exists but is temporarily unavailable - Use
hiddenwhen you want to completely hide fields that aren't relevant to the current form state
All Supported Components
Both disabled and hidden props are available on all smart field components:
SmartInputSmartSelectSmartComboboxSmartCheckboxSmartRadioGroupSmartDatePickerSmartSliderSmartDualRangeSliderSmartTagsSmartFileUploadSmartAutoSuggestTagsSmartBasicRichTextbox
Query Parameters
Automatically include URL query parameters in form submissions.
Include ALL query parameters:
<SmartForm
api="/api/submit"
includeQueryParams={true}
>
<SmartInput field="name" label="Name" />
</SmartForm>Include SPECIFIC query parameters:
<SmartForm
api="/api/submit"
includeQueryParams={true}
queryParamsToInclude={['userId', 'companyId']}
>
<SmartInput field="name" label="Name" />
</SmartForm>Example:
- URL:
/form?userId=123&companyId=456 - Form data:
{ name: "John" } - Submitted:
{ userId: "123", companyId: "456", name: "John" }
Behavior:
- Form field values always override query params if names conflict
- Works with both form submission and draft saving
- If
queryParamsToIncludeis omitted, all query params are included
Draft Saving
Local Storage:
<SmartForm
enableLocalStorage={true}
storageKey="my-form-draft"
allowSaveDraft={true}
>
{/* Fields */}
</SmartForm>API-based Draft:
<SmartForm
allowSaveDraft={true}
saveDraftApi="/api/drafts"
>
{/* Fields */}
</SmartForm>Data Transformation
Transform form data before submission:
<SmartForm
transformData={(data) => ({
...data,
skills: data.skills?.join(','),
timestamp: new Date().toISOString()
})}
>
{/* Fields */}
</SmartForm>Initial Values
Pre-populate form fields:
<SmartForm
initialData={{
name: 'John Doe',
email: '[email protected]',
country: 'us'
}}
>
{/* Fields */}
</SmartForm>Authentication
Enable automatic Bearer token authentication:
<SmartForm
authentication={{
enable: true,
refreshTokenEndpoint: "/api/auth/refresh"
}}
>
{/* Fields */}
</SmartForm>The library will:
- Get access token from localStorage
- Include it as
Authorization: Bearer <token> - Automatically refresh if token expires
- Retry the request with new token
🎨 Theming & Customization
CSS Variables
Override the default theme by defining CSS variables:
:root {
--radius: 0.5rem;
--background: white;
--foreground: black;
--primary: #3b82f6;
--primary-foreground: white;
--border: #e5e7eb;
--input: #e5e7eb;
--ring: #3b82f6;
}
.dark {
--background: #1f2937;
--foreground: white;
--primary: #60a5fa;
}Tailwind Classes
Customize using Tailwind utility classes:
<SmartForm className="max-w-4xl mx-auto p-8 bg-gray-50 rounded-xl shadow-lg">
<SmartInput
field="name"
label="Name"
className="border-blue-500 focus:ring-blue-500"
/>
</SmartForm>Custom Submit Button
Use BaseSmartForm with custom buttons:
import { BaseSmartForm, useSmartForm } from '@algodomain/smart-forms'
function CustomForm() {
return (
<BaseSmartForm api="/api/submit">
<SmartInput field="name" label="Name" />
<CustomSubmitButton />
</BaseSmartForm>
)
}
function CustomSubmitButton() {
const { submitForm, isLoading } = useSmartForm()
return (
<button onClick={submitForm} disabled={isLoading}>
{isLoading ? 'Submitting...' : 'Submit'}
</button>
)
}🪝 Hooks & Context
useSmartForm
Access form context and methods.
import { useSmartForm } from '@algodomain/smart-forms'
function MyComponent() {
const {
formData, // Current form values
errors, // Validation errors
isLoading, // Submission loading state
isDraftSaving, // Draft saving state
submitForm, // Submit function
saveDraft, // Save draft function
resetForm, // Reset to initial values
updateField, // Update specific field
config // Form configuration
} = useSmartForm()
return <button onClick={submitForm}>Submit</button>
}useFormField
Access individual field state (used internally by field components).
import { useFormField } from '@algodomain/smart-forms'
function CustomField({ field }) {
const { value, error, onChange } = useFormField(field)
return (
<input
value={value || ''}
onChange={(e) => onChange(e.target.value)}
/>
)
}💡 Examples
Complete Registration Form
import { SmartForm } from '@algodomain/smart-forms'
import { SmartInput, SmartSelect, SmartCheckbox, SmartDatePicker } from '@algodomain/smart-forms/fields'
import { FieldEmail, FieldPassword } from '@algodomain/smart-forms/opinionated'
import { z } from 'zod'
import { toast } from 'react-toastify'
export function RegistrationForm() {
return (
<SmartForm
api="https://api.example.com/register"
method="POST"
submitButtonText="Register"
submitDisabled={(formData) => !formData.agreeToTerms}
onSuccess={(data) => {
toast.success('Account created successfully!')
}}
onError={(error) => {
toast.error('Registration failed.')
}}
>
<SmartInput
field="fullName"
label="Full Name"
validation={z.string().min(3)}
required
/>
<FieldEmail field="email" required />
<FieldPassword field="password" required />
<SmartSelect
field="country"
label="Country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
{ value: 'uk', label: 'United Kingdom' }
]}
required
/>
<SmartSelect
field="state"
label="State"
options={stateOptions}
disabled={(formData) => !formData.country}
/>
<SmartDatePicker
field="birthDate"
label="Date of Birth"
validation={z.date().max(new Date())}
required
/>
<SmartCheckbox
field="terms"
label="I agree to the Terms and Conditions"
validation={z.boolean().refine(val => val === true)}
required
/>
</SmartForm>
)
}Multi-Tab Job Application
import { MultiTabSmartForm, Tab } from '@algodomain/smart-forms'
import { SmartInput, SmartTags, SmartDualRangeSlider } from '@algodomain/smart-forms/fields'
import { FieldEmail, FieldPhone } from '@algodomain/smart-forms/opinionated'
import { z } from 'zod'
export function JobApplicationForm() {
return (
<MultiTabSmartForm
api="/api/applications"
method="POST"
showProgressBar={true}
showTabNumbers={true}
allowSaveDraft={true}
enableLocalStorage={true}
storageKey="job-application"
>
<Tab title="Personal Info">
<SmartInput
field="fullName"
label="Full Name"
validation={z.string().min(3)}
required
/>
<FieldEmail field="email" required />
<FieldPhone field="phone" required />
</Tab>
<Tab title="Experience">
<SmartDualRangeSlider
minField="minExperience"
maxField="maxExperience"
label="Years of Experience"
min={0}
max={40}
step={1}
/>
<SmartTags
field="skills"
label="Skills"
validation={z.array(z.string()).min(3)}
required
/>
</Tab>
</MultiTabSmartForm>
)
}Form with Query Parameters
// URL: /create-job?userId=123&companyId=456
<SmartForm
api="/api/jobs"
includeQueryParams={true}
queryParamsToInclude={['userId', 'companyId']}
>
<SmartInput field="jobTitle" label="Job Title" required />
<SmartInput field="location" label="Location" required />
</SmartForm>
// Submitted data will include:
// { userId: "123", companyId: "456", jobTitle: "...", location: "..." }🐛 Troubleshooting
Error: "useSmartForm must be used within a SmartFormProvider"
Cause: Field components used outside a form wrapper.
Solution: Wrap fields in a form component:
// ❌ Wrong
<SmartInput field="name" label="Name" />
// ✅ Correct
<SmartForm api="/api/submit">
<SmartInput field="name" label="Name" />
</SmartForm>Styles Not Loading
Cause: CSS not imported.
Solution:
import '@algodomain/smart-forms/style.css'
import 'react-toastify/dist/ReactToastify.css'For Tailwind v4, add @source directives:
@source "../node_modules/@algodomain/smart-forms/dist/index.js";Form Not Submitting
Cause: Missing API endpoint or validation errors.
Solution:
- Ensure
apiprop is set - Check console for validation errors
- Use
logFormData={true}:
<SmartForm api="/api/submit" logFormData={true}>
{/* Fields */}
</SmartForm>TypeScript Errors
Solution: Install type definitions:
npm install @types/react @types/react-dom📖 Validation with Zod
All fields support Zod schemas for validation:
import { z } from 'zod'
// String validation
validation={z.string().min(3, "Too short").max(50, "Too long")}
// Email
validation={z.string().email("Invalid email")}
// Number
validation={z.number().min(0).max(100)}
// Array
validation={z.array(z.string()).min(1, "Required")}
// Date
validation={z.date().max(new Date(), "Cannot be future")}
// Boolean
validation={z.boolean().refine(val => val === true, {
message: "Must be true"
})}
// Enum
validation={z.enum(['option1', 'option2'])}
// Custom
validation={z.string().refine(val => val.includes('@'), {
message: "Must contain @"
})}🤝 Contributing
Contributions welcome! Please visit our GitHub repository.
📄 License
MIT License - feel free to use in your projects!
🙋 Support
- Issues: GitHub Issues
- Email: [email protected]
- npm: @algodomain/smart-forms
Built with ❤️ by AlgoDomain
