npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

Iโ€™ve always been into building performant and accessible sites, but lately Iโ€™ve been taking it extremely seriously. So much so that Iโ€™ve been building a tool to help me optimize and monitor the sites that I build to make sure that Iโ€™m making an attempt to offer the best experience to those who visit them. If youโ€™re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, ๐Ÿ‘‹, Iโ€™m Ryan Hefnerย  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If youโ€™re interested in other things Iโ€™m working on, follow me on Twitter or check out the open source projects Iโ€™ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soonโ€“ish.

Open Software & Tools

This site wouldnโ€™t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you ๐Ÿ™

ยฉ 2026 โ€“ย Pkg Stats / Ryan Hefner

@fivexlabs/conform-react

v1.1.0

Published

๐Ÿš€ A powerful React library for building dynamic, conditional forms using JSON schemas with React Hook Form integration. Create complex forms declaratively with built-in validation, accessibility, and customizable components. Made with โค๏ธ by Fivex Labs.

Downloads

10

Readme

@fivexlabs/conform-react

npm version License: MIT TypeScript

โœจ Features

๐ŸŽฏ Core Features

  • ๐Ÿ“‹ Declarative Schema Definition: Define entire forms using JSON schemas
  • ๐Ÿ”„ Dynamic Conditional Logic: Show/hide fields based on other field values
  • โœ… Comprehensive Validation: Built-in and custom validation with internationalization support
  • ๐ŸŽจ Customizable Components: Provide your own React components for any field type
  • โ™ฟ Accessibility First: WCAG compliant forms with proper ARIA attributes
  • ๐Ÿš€ Performance Optimized: Built on React Hook Form for optimal performance
  • ๐Ÿ“ฆ TypeScript Ready: Full TypeScript support with comprehensive type definitions

๐Ÿ”ฅ Advanced Features (New!)

  • ๐Ÿ“ Smart File Upload: Drag & drop interface with progress tracking, image preview, and validation
  • ๐Ÿ” Async Autocomplete: Search-as-you-type with debouncing, templates, and API integration
  • ๐Ÿ“… Business Date/Time Picker: Business rules, timezone support, and restriction handling
  • ๐Ÿ”— Cross-field Validation: Dependencies between fields with real-time validation
  • ๐Ÿงฎ Computed Fields: Auto-calculated values based on other field data
  • โšก Real-time Updates: Live form state management and analytics

๐Ÿ“ฆ Installation

npm install @fivexlabs/conform-react react-hook-form yup date-fns
# or
yarn add @fivexlabs/conform-react react-hook-form yup date-fns

Note: date-fns is required for the advanced date/time picker functionality.

๐Ÿš€ Quick Start

import React from 'react';
import { FormRenderer, FormSchema } from '@fivexlabs/conform-react';

const schema: FormSchema = {
  title: "User Registration",
  fields: [
    {
      name: "fullName",
      label: "Full Name",
      type: "text",
      validation: { required: true, minLength: 2 }
    },
    {
      name: "email",
      label: "Email Address",
      type: "email",
      validation: { required: true, email: true }
    },
    {
      name: "subscribe",
      label: "Subscribe to newsletter?",
      type: "checkbox",
      defaultValue: false
    },
    {
      name: "reason",
      label: "Why do you want to subscribe?",
      type: "textarea",
      visibleWhen: { subscribe: true },
      validation: { required: true, maxLength: 200 }
    }
  ]
};

function App() {
  const handleSubmit = (data: Record<string, any>) => {
    console.log('Form submitted:', data);
  };

  return (
    <FormRenderer
      schema={schema}
      onSubmit={handleSubmit}
      onFormChange={(data) => console.log('Form changed:', data)}
    />
  );
}

๐Ÿ”ฅ Advanced Features Showcase

๐Ÿ“ Smart File Upload

Create powerful file upload experiences with drag & drop, progress tracking, and validation:

{
  name: "documents",
  type: "fileUpload",
  label: "Project Documents",
  props: {
    multiple: true,
    accept: ['.pdf', '.docx', '.jpg', '.png'],
    maxSize: 10 * 1024 * 1024, // 10MB
    maxFiles: 5,
    preview: true,
    upload: {
      endpoint: '/api/upload',
      method: 'POST',
      headers: { 'Authorization': 'Bearer token123' }
    }
  },
  onUploadProgress: (progress, file) => console.log(`${file.name}: ${progress}%`),
  onUploadComplete: (response, file) => console.log('Upload completed:', response)
}

๐Ÿ” Async Autocomplete

Build smart search interfaces with real-time suggestions:

{
  name: "assignee",
  type: "autocomplete",
  label: "Project Assignee",
  props: {
    searchEndpoint: '/api/users/search',
    displayKey: 'name',
    valueKey: 'id',
    debounce: 300,
    minChars: 2,
    template: '{{name}} - {{department}} ({{email}})',
    multiple: false
  }
}

๐Ÿ“… Business Date/Time Picker

Handle complex business rules with smart date/time selection:

{
  name: "deadline",
  type: "dateTime",
  label: "Project Deadline",
  props: {
    includeTime: true,
    format: 'yyyy-MM-dd HH:mm',
    restrictions: {
      minDate: 'today',
      businessDaysOnly: true,
      disabledDays: ['saturday', 'sunday'],
      disabledDates: ['2024-12-25', '2024-01-01']
    }
  }
}

๐Ÿ”— Cross-field Validation

Create intelligent forms with field dependencies:

{
  name: "endDate",
  type: "dateTime",
  label: "Project End Date",
  validation: {
    custom: async (value, formData) => {
      if (value <= formData.startDate) {
        return 'End date must be after start date';
      }
      return true;
    },
    dependencies: ['startDate'] // Re-validate when startDate changes
  }
}

๐Ÿงฎ Computed Fields

Auto-calculate values based on other field data:

{
  name: "totalCost",
  type: "text",
  label: "Total Cost",
  props: { disabled: true }, // Read-only
  computed: {
    formula: (formData) => {
      const hours = formData.estimatedHours || 0;
      const rate = formData.hourlyRate || 0;
      return `$${(hours * rate).toFixed(2)}`;
    },
    dependencies: ['estimatedHours', 'hourlyRate']
  }
}

๐Ÿ“š Documentation

Basic Form Schema

A form schema defines the structure, validation, and behavior of your form:

interface FormSchema {
  title?: string;
  description?: string;
  fields: (FormField | FieldGroup)[];
  layout?: LayoutConfig;
  submitButtonText?: string;
  resetButtonText?: string;
  showResetButton?: boolean;
}

Field Types

Text Input Fields

{
  name: "username",
  label: "Username",
  type: "text", // "text" | "email" | "password" | "url" | "tel"
  placeholder: "Enter your username",
  validation: {
    required: true,
    minLength: 3,
    pattern: "^[a-zA-Z0-9_]+$"
  },
  validationMessages: {
    pattern: "Username can only contain letters, numbers, and underscores"
  }
}

Select Fields

{
  name: "country",
  label: "Country",
  type: "select",
  options: [
    { label: "United States", value: "us" },
    { label: "Canada", value: "ca" },
    { label: "United Kingdom", value: "uk" }
  ],
  validation: { required: true }
}

Array Fields (Repeatable Sections)

{
  name: "addresses",
  label: "Addresses",
  type: "array",
  minItems: 1,
  maxItems: 3,
  itemSchema: {
    fields: [
      {
        name: "street",
        label: "Street Address",
        type: "text",
        validation: { required: true }
      },
      {
        name: "city",
        label: "City",
        type: "text",
        validation: { required: true }
      }
    ]
  }
}

Conditional Logic

Simple Conditional Syntax

{
  name: "otherReason",
  label: "Please specify",
  type: "text",
  visibleWhen: { reason: "other" }, // Show when reason equals "other"
  disabledWhen: { status: "readonly" } // Disable when status equals "readonly"
}

Advanced Conditional Logic

{
  name: "discount",
  label: "Discount Code",
  type: "text",
  conditional: {
    and: [
      { field: "membershipType", operator: "equals", value: "premium" },
      { field: "orderAmount", operator: "greaterThan", value: 100 }
    ]
  }
}

Complex Conditions with MongoDB-style Operators

{
  name: "specialOffer",
  label: "Special Offer",
  type: "checkbox",
  visibleWhen: {
    age: { $gte: 18 },
    country: { $in: ["us", "ca", "uk"] },
    email: { $contains: "@company.com" }
  }
}

Validation

Built-in Validation Rules

{
  validation: {
    required: true,
    minLength: 5,
    maxLength: 50,
    min: 0,
    max: 100,
    pattern: "^[A-Z][a-z]+$",
    email: true // For email fields
  }
}

Custom Validation

{
  validation: {
    custom: async (value) => {
      // Async validation example
      const isUnique = await checkUsernameUniqueness(value);
      return isUnique || "Username is already taken";
    }
  }
}

Field Groups

{
  type: "group",
  title: "Personal Information",
  description: "Please provide your personal details",
  collapsible: true,
  fields: [
    {
      name: "firstName",
      label: "First Name",
      type: "text",
      validation: { required: true }
    },
    {
      name: "lastName",
      label: "Last Name",
      type: "text",
      validation: { required: true }
    }
  ]
}

Custom Components

You can provide your own React components for any field type:

import { TextField } from '@mui/material';

const customComponents = {
  text: ({ field, value, onChange, error, ...props }) => (
    <TextField
      label={field.label}
      value={value || ''}
      onChange={(e) => onChange(e.target.value)}
      error={!!error}
      helperText={error}
      fullWidth
      {...props}
    />
  ),
  select: CustomSelectComponent,
  // ... other custom components
};

<FormRenderer
  schema={schema}
  customComponents={customComponents}
  onSubmit={handleSubmit}
/>

Advanced Usage

Custom Rendering

<FormRenderer
  schema={schema}
  onSubmit={handleSubmit}
  renderSubmitButton={(props) => (
    <CustomButton loading={props.loading} onClick={props.onClick}>
      {props.text}
    </CustomButton>
  )}
  renderErrorSummary={(errors) => (
    <CustomErrorDisplay errors={errors} />
  )}
  renderFieldWrapper={({ field, children, error }) => (
    <div className="custom-field-wrapper">
      {children}
      {error && <span className="error-icon">โš ๏ธ</span>}
    </div>
  )}
/>

Form State Management

const FormWithState = () => {
  const [formData, setFormData] = useState({});
  
  return (
    <FormRenderer
      schema={schema}
      initialValues={{ username: 'defaultUser' }}
      onSubmit={handleSubmit}
      onFormChange={setFormData}
      onFieldChange={(fieldName, value, allValues) => {
        console.log(`Field ${fieldName} changed to:`, value);
      }}
    />
  );
};

๐ŸŽจ Styling

The library provides unstyled components by default with semantic CSS classes for easy styling:

.conform-form {
  /* Main form container */
}

.form-field {
  /* Individual field wrapper */
}

.form-group {
  /* Field group container */
}

.form-error {
  /* Error message styling */
}

For Tailwind CSS users, the default components include Tailwind classes that you can customize.

๐Ÿงช Testing

npm test

๐Ÿ“– API Reference

FormRenderer Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | schema | FormSchema | โœ… | The JSON schema defining the form structure | | onSubmit | (data: Record<string, any>) => void \| Promise<void> | โœ… | Called when form is submitted | | initialValues | Record<string, any> | โŒ | Initial form values | | onFormChange | (data: Record<string, any>) => void | โŒ | Called when any field changes | | onFieldChange | (fieldName: string, value: any, allValues: Record<string, any>) => void | โŒ | Called when a specific field changes | | customComponents | Record<string, React.ComponentType<any>> | โŒ | Custom components for field types | | loading | boolean | โŒ | Shows loading state | | disabled | boolean | โŒ | Disables entire form |

๐Ÿ“‹ Changelog

See CHANGELOG.md for a detailed history of all changes and new features.

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿข About Fivex Labs

Fivex Labs is a technology company focused on building innovative tools and libraries for modern web development. We believe in creating solutions that are both powerful and developer-friendly.

Visit us at fivexlabs.com to learn more about our work and other open-source projects.