JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 68
  • Score
    100M100P100Q51549F
  • License MIT

A customizable form field components built with TypeScript

Package Exports

  • form-input-fields
  • form-input-fields/dist/index.es.js
  • form-input-fields/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (form-input-fields) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Form Fields Components

A collection of Material-UI form field components with Formik integration.

Version 1.0.16

More control in the progress of development.

Installation

Prerequisites

Before installing the form-input-fields package, make sure you have the following peer dependencies installed in your project:

  • React 16.8.0 or later
  • React DOM 16.8.0 or later
  • Material-UI (MUI) 5.0.0 or later
  • Formik 2.0.0 or later
  • @mui/x-date-pickers 6.0.0 or later
  • dayjs 1.11.0 or later

Using npm

npm install form-input-fields @mui/material @emotion/react @emotion/styled formik @mui/x-date-pickers dayjs

Using yarn

yarn add form-input-fields @mui/material @emotion/react @emotion/styled formik @mui/x-date-pickers dayjs

Using pnpm

pnpm add form-input-fields @mui/material @emotion/react @emotion/styled formik @mui/x-date-pickers dayjs

Peer Dependencies

Make sure your project includes these peer dependencies:

{
  "devDependencies": {
    "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
    "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
    "@mui/material": "^5.0.0",
    "@emotion/react": "^11.0.0",
    "@emotion/styled": "^11.0.0",
    "formik": "^2.0.0",
    "@mui/x-date-pickers": "^6.0.0",
    "dayjs": "^1.11.0"
  }
}

TypeScript

This package includes TypeScript type definitions. No additional type packages are needed.

Browser Support

The form fields support all modern browsers including:

  • Chrome (latest 2 versions)
  • Firefox (latest 2 versions)
  • Safari (latest 2 versions)
  • Edge (latest 2 versions)

For Internet Explorer 11 support, you'll need to include polyfills. See Browser Support for more details.

Next Steps

After installation, you can import and use the components in your application:

import { FormTextField, FormDateField, FormMaskField, FormSwitch } from 'form-input-fields';

Troubleshooting

If you encounter any issues during installation, try the following:

  1. Clear your package manager's cache:

    npm cache clean --force
    # or
    yarn cache clean
    # or
    pnpm store prune
  2. Delete node_modules and package-lock.json (or yarn.lock/pnpm-lock.yaml)

  3. Reinstall dependencies:

    npm install
    # or
    yarn install
    # or
    pnpm install

If you're still experiencing issues, please reach me at vladimir.vorobiev@gmail.com with details about your environment and the error message you're seeing.

Table of Contents


FormTextField

A versatile text input field component that integrates Material-UI's TextField with Formik form handling.

Features

  • Seamless Formik Integration: Automatically handles form state, validation, and error messages
  • Material-UI Styling: Consistent look and feel with Material Design
  • TypeScript Support: Fully typed component with proper type definitions
  • Flexible Props: Supports all standard TextField props from Material-UI
  • Error Handling: Built-in error state management with Formik
  • Responsive Design: Works well across different screen sizes

Basic Usage

import { Formik, Field } from 'formik';
import { FormTextField } from 'form-input-fields';

<Formik initialValues={{ username: '' }} onSubmit={values => console.log(values)}>
  <Field
    component={FormTextField}
    name="username"
    label="Username"
    placeholder="Enter your username"
  />
</Formik>;

Props

The FormTextField component accepts all props from FormTextFieldProps, FieldProps (Formik), and Material-UI's TextFieldProps.

FormTextFieldProps Interface

| Prop | Type | Default | Description | | ---------- | ---------------- | ---------- | -------------------------------------------------------------------------------------- | ---------- | --------------------------------- | | onChange | function | - | Custom change handler that overrides Formik's | | onBlur | function | - | Custom blur handler that overrides Formik's | | variant | 'standard' | 'outlined' | 'filled' | 'standard' | The variant of the MUI TextField. | | sx | SxProps<Theme> | - | The system prop that allows defining system overrides as well as additional CSS styles |

Common Props (from FieldProps & TextFieldProps)

Prop Type Required Description
name string Yes Field name in Formik values
label string No Field label
helperText string No Custom helper text
error boolean No Error state (auto-managed by Formik)
disabled boolean No Disabled state
required boolean No Required field indicator
type string 'text' Input type (text, email, password, etc.)
Other TextFieldProps No All Material-UI TextField props are supported

Examples

Basic Text Input

<Field
  component={FormTextField}
  name="username"
  label="Username"
  placeholder="Enter your username"
  fullWidth
  margin="normal"
  variant="outlined" // <-- Example with outlined variant
/>

Text Field with Formik

<Formik
  initialValues={{ email: '' }}
  validate={values => {
    const errors = {};
    if (!values.email) {
      errors.email = 'Required';
    } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
      errors.email = 'Invalid email address';
    }
    return errors;
  }}
  onSubmit={values => console.log(values)}
>
  {({ errors, touched }) => (
    <Field
      component={FormTextField}
      name="email"
      label="Email"
      type="email"
      error={touched.email && Boolean(errors.email)}
      helperText={touched.email && errors.email}
      required
    />
  )}
</Formik>

Custom Validation

<Field
  component={FormTextField}
  name="password"
  label="Password"
  type="password"
  inputProps={{
    minLength: 8,
    pattern: '(?=.*d)(?=.*[a-z])(?=.*[A-Z]).{8,}',
  }}
  helperText="Must contain at least 8 characters, including uppercase, lowercase, and numbers"
  required
/>

FormDropDownField

A customizable dropdown/select component that integrates Material-UI's Select with Formik form handling.

Features

  • Seamless Formik Integration: Automatically handles form state, validation, and error messages
  • Material-UI Styling: Consistent look and feel with Material Design
  • TypeScript Support: Fully typed component with proper type definitions
  • Flexible Data Binding: Works with array of objects with id and description properties
  • Optional Default Selection: Add a default "Select" option with customizable text
  • Form Validation: Built-in error state management with Formik
  • Responsive Design: Works well across different screen sizes

Basic Usage

import { Formik, Field } from 'formik';
import { FormDropDownField } from 'form-input-fields';

const items = [
  { id: '1', description: 'Option 1' },
  { id: '2', description: 'Option 2' },
  { id: '3', description: 'Option 3' },
];

<Formik initialValues={{ category: '' }} onSubmit={values => console.log(values)}>
  <Field
    component={FormDropDownField}
    name="category"
    label="Category"
    items={items}
    addInputSelect={true}
  />
</Formik>;

Props

The FormDropDownField component accepts all props from FormDropDownFieldProps, FieldProps (Formik), and Material-UI's TextFieldProps (with some exceptions).

FormDropDownFieldProps Interface

| Prop | Type | Default | Description | | ---------------- | ----------------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------- | --------------------------------- | | items | Array<{ id: string | number; description: string }> | [] | Array of items to display in the dropdown | | addInputSelect | boolean | false | Whether to show a default "Select" option as the first item | | selectText | string | 'Select' | Text to display for the default "Select" option | | required | boolean | false | Whether the field is required | | disabled | boolean | false | Whether the field is disabled | | className | string | - | Custom class name for the root element | | helperText | string | - | Helper text to display below the field | | error | boolean | - | Error state of the field (overrides Formik error state) | | onChange | (value: any) => void | - | Custom change handler | | onBlur | (event: React.FocusEvent<HTMLInputElement>) => void | - | Custom blur handler | | variant | 'standard' | 'outlined' | 'filled' | 'standard' | The variant of the MUI TextField. | | sx | SxProps<Theme> | - | The system prop that allows defining system overrides as well as additional CSS styles |

Examples

Basic Dropdown

const items = [
  { id: 'us', description: 'United States' },
  { id: 'ca', description: 'Canada' },
  { id: 'uk', description: 'United Kingdom' },
];

<Field
  component={FormDropDownField}
  name="country"
  label="Country"
  items={items}
  fullWidth
  variant="outlined" // <-- Example with outlined variant
/>;
<Field
  component={FormDropDownField}
  name="category"
  label="Category"
  items={categories}
  addInputSelect={true}
  selectText="Select a category"
  helperText="Please select a category from the list"
/>

Required Dropdown with Validation

<Formik
  initialValues={{ department: '' }}
  validationSchema={Yup.object({
    department: Yup.string().required('Department is required'),
  })}
  onSubmit={values => console.log(values)}
>
  {({ errors, touched }) => (
    <Form>
      <Field
        component={FormDropDownField}
        name="department"
        label="Department"
        items={departments}
        addInputSelect={true}
        required
        error={touched.department && Boolean(errors.department)}
        helperText={touched.department && errors.department}
      />
      <Button type="submit" variant="contained" color="primary">
        Submit
      </Button>
    </Form>
  )}
</Formik>

FormDateField

A date input field component with Material-UI and Formik integration, powered by MUI X Date Pickers.

Features

  • Material-UI Integration: Consistent styling with other form components
  • Formik Integration: Seamless form state management with error handling
  • Day.js Support: Lightweight date library for date manipulation
  • Custom Date Formatting: Flexible date display formats
  • Date Validation: Built-in min/max date validation
  • Read-Only Support: Can be configured as read-only
  • TypeScript Support: Full type safety with exported interfaces
  • Helper Text Display: Show date format or custom helper text
  • Today Button: Optional today button in date picker

Available Date Formats

The component uses predefined date format constants from date.ts:

FORM_DATE_FORMAT

export const FORM_DATE_FORMAT = {
  short: 'YYYY-MM-DD',
  long: 'MM/DD/YYYY hh:mm A',
  custom: 'DD MMMM YYYY hh:mm A',
};

DATE_PICKER_DATE_FORMAT

export const DATE_PICKER_DATE_FORMAT = {
  short: 'DD/MM/YYYY',
};

DATE_PICKER_MONTH_YEAR_FORMAT

export const DATE_PICKER_MONTH_YEAR_FORMAT = {
  short: 'MM/YYYY',
  long: 'MMMM YYYY',
};

Importing Date Constants

import {
  FORM_DATE_FORMAT,
  DATE_PICKER_DATE_FORMAT,
  DATE_PICKER_MONTH_YEAR_FORMAT
} from "form-input-fields/date";

// Use predefined formats
<Field
  component={FormDateField}
  name="birthDate"
  format={FORM_DATE_FORMAT.short}  // 'YYYY-MM-DD'
/>

// Or use custom format
<Field
  component={FormDateField}
  name="eventDate"
  format="DD/MM/YYYY HH:mm"  // Custom format
/>

Usage with Formik

import { Formik, Field } from 'formik';
import { FormDateField, FormDateFieldProps } from 'form-input-fields';
import { FORM_DATE_FORMAT } from 'form-input-fields/date';
import dayjs from 'dayjs';

<Formik
  initialValues={{ birthDate: null, appointmentDate: null }}
  onSubmit={values => console.log(values)}
>
  {/* Basic usage */}
  <Field
    component={FormDateField}
    name="birthDate"
    label="Birth Date"
    format={FORM_DATE_FORMAT.short}
  />

  {/* Advanced usage with validation */}
  <Field
    component={FormDateField}
    name="appointmentDate"
    label="Appointment Date"
    format="DD/MM/YYYY"
    minDate={dayjs()}
    disablePast={true}
    showTodayButton={true}
    showDateFormat={true}
    onChange={(value, context) => {
      console.log('Selected date:', value);
      console.log('Formatted value:', context.formattedValue);
    }}
  />
</Formik>;

Props

The FormDateField component accepts all props from FormDateFieldProps, FieldProps, and TextFieldProps.

FormDateFieldProps Interface

Prop Type Default Description
format string FORM_DATE_FORMAT.short Date format string using dayjs format tokens
minDate Dayjs - Minimum selectable date
maxDate Dayjs - Maximum selectable date
disablePast boolean false Disable past dates
disableFuture boolean false Disable future dates
showTodayButton boolean false Show today button in the picker
readOnly boolean false Make the field read-only
showDateFormat boolean false Show the date format as helper text
onChange function - Custom change handler with additional context
sx SxProps<Theme> - The system prop that allows defining system overrides as well as additional CSS styles

Common Props (from FieldProps & TextFieldProps)

Prop Type Required Description
name string Yes Field name in Formik values
label string No Field label
helperText string No Custom helper text
error boolean No Error state
disabled boolean No Disabled state
Other TextFieldProps No All Material-UI TextField props are supported

Examples

Basic Date Input

<Field component={FormDateField} name="birthDate" label="Birth Date" format="DD/MM/YYYY" />

Date with Validation

<Field
  component={FormDateField}
  name="startDate"
  label="Start Date"
  minDate={dayjs()}
  disablePast={true}
  showDateFormat={true}
  helperText="Select a future date"
/>

Appointment Scheduler

<Field
  component={FormDateField}
  name="appointmentDate"
  label="Appointment Date"
  format="DD MMMM YYYY"
  minDate={dayjs().add(1, 'day')}
  maxDate={dayjs().add(3, 'month')}
  showTodayButton={true}
  showDateFormat={true}
/>

Read-Only Date Display

<Field
  component={FormDateField}
  name="createdDate"
  label="Created Date"
  format="DD/MM/YYYY HH:mm"
  readOnly={true}
/>

Custom Change Handler

<Field
  component={FormDateField}
  name="eventDate"
  label="Event Date"
  format="YYYY-MM-DD"
  onChange={(value, context) => {
    console.log('Selected date:', value);
    console.log('Formatted value:', context.formattedValue);
    console.log('Validation error:', context.validationError);

    // Custom logic here
    if (value && value.day() === 0) {
      alert('Events cannot be scheduled on Sundays');
    }
  }}
/>

Date Range (Start/End Dates)

<Field
  component={FormDateField}
  name="startDate"
  label="Start Date"
  format="DD/MM/YYYY"
  maxDate={values.endDate ? dayjs(values.endDate) : undefined}
/>

<Field
  component={FormDateField}
  name="endDate"
  label="End Date"
  format="DD/MM/YYYY"
  minDate={values.startDate ? dayjs(values.startDate) : undefined}
/>

FormCheckboxField

A customizable checkbox component with Material-UI and Formik integration, providing consistent styling and behavior across your application.

Features

  • Material-UI Integration: Consistent styling with Material-UI's design system
  • Formik Integration: Seamless form state management with error handling
  • Custom Styling: Easy customization through Material-UI's styling system
  • TypeScript Support: Full type safety with exported interfaces
  • Accessibility: Built with accessibility in mind, following WAI-ARIA guidelines
  • Responsive Design: Works well on all screen sizes

Basic Usage

import { Formik, Field } from 'formik';
import { FormCheckboxField } from 'form-input-fields';

// Basic usage
<FormCheckboxField
  id="terms"
  label="I agree to the terms and conditions"
  checked={false}
  onChange={(e) => console.log('Checked:', e.target.checked)}
/>

// With Formik
<Formik
  initialValues={{ termsAccepted: false }}
  onSubmit={(values) => console.log(values)}
>
  {({ values }) => (
    <Field
      name="termsAccepted"
      component={({ field, form }) => (
        <FormCheckboxField
          {...field}
          label="I agree to the terms and conditions"
          checked={field.value}
          onChange={(e) => {
            form.setFieldValue(field.name, e.target.checked);
          }}
        />
      )}
    />
  )}
</Formik>

Props

The FormCheckboxField component accepts all props from FormCheckboxFieldProps and Material-UI's CheckboxProps.

FormCheckboxFieldProps Interface

Prop Type Default Description
id string - Unique identifier for the checkbox
label string - Label text displayed next to the checkbox
checked boolean false Whether the checkbox is checked
onChange function - Callback when checkbox state changes
disabled boolean false Disable the checkbox
required boolean false Mark the field as required
color string 'primary' Color of the checkbox when checked
size string 'medium' Size of the checkbox ('small' or 'medium')
labelPlacement string 'end' Position of the label ('end', 'start', 'top', 'bottom')

Examples

Basic Checkbox

<FormCheckboxField
  id="notifications"
  label="Enable email notifications"
  checked={notificationsEnabled}
  onChange={e => setNotificationsEnabled(e.target.checked)}
  color="secondary"
/>

Checkbox with Formik

<Formik
  initialValues={{
    termsAccepted: false,
    newsletter: true,
    notifications: false,
  }}
  onSubmit={values => console.log('Form values:', values)}
>
  {({ values }) => (
    <Form>
      <Field
        name="termsAccepted"
        component={({ field, form }) => (
          <FormCheckboxField
            {...field}
            label="I agree to the terms and conditions"
            checked={field.value}
            onChange={e => form.setFieldValue(field.name, e.target.checked)}
            required
          />
        )}
      />

      <Field
        name="newsletter"
        component={({ field, form }) => (
          <FormCheckboxField
            {...field}
            label="Subscribe to newsletter"
            checked={field.value}
            onChange={e => form.setFieldValue(field.name, e.target.checked)}
            color="secondary"
          />
        )}
      />

      <Button type="submit" variant="contained" color="primary">
        Submit
      </Button>
    </Form>
  )}
</Formik>

Custom Styled Checkbox

import { makeStyles } from '@mui/styles';

const useStyles = makeStyles(theme => ({
  root: {
    margin: theme.spacing(1),
  },
  labelRoot: {
    color: theme.palette.primary.main,
    fontWeight: 500,
  },
}));

function CustomCheckbox() {
  const classes = useStyles();

  return (
    <FormCheckboxField
      id="custom-checkbox"
      label="Custom Styled Checkbox"
      checked={false}
      onChange={() => {}}
      classes={{
        root: classes.root,
        label: classes.labelRoot,
      }}
      color="primary"
    />
  );
}

FormSwitch

A customizable switch component with Material-UI and Formik integration, providing consistent styling and behavior for boolean inputs across your application.

Features

  • Material-UI Integration: Consistent styling with Material-UI's design system
  • Formik Integration: Seamless form state management with error handling
  • Flexible Label Placement: Support for different label positions
  • TypeScript Support: Full type safety with exported interfaces
  • Accessibility: Built with accessibility in mind, following WAI-ARIA guidelines
  • Error Handling: Built-in error state management with Formik
  • Responsive Design: Works well on all screen sizes

Basic Usage

import { Formik, Field } from 'formik';
import { FormSwitch } from 'form-input-fields';

// Basic usage
<FormSwitch
  label="Enable Notifications"
  checked={notificationsEnabled}
  onChange={(e, checked) => setNotificationsEnabled(checked)}
/>

// With Formik
<Formik
  initialValues={{ notifications: false }}
  onSubmit={(values) => console.log(values)}
>
  <Field
    component={FormSwitch}
    name="notifications"
    label="Enable Notifications"
    helperText="Receive email notifications"
  />
</Formik>

Props

The FormSwitch component accepts all props from FormSwitchProps, FieldProps (Formik), and Material-UI's SwitchProps.

FormSwitchProps Interface

Prop Type Default Description
label string - Label text displayed next to the switch
labelPlacement string 'end' Position of label ('top', 'start', 'bottom', 'end')
color string 'primary' Switch color ('primary', 'secondary', 'error', 'info', 'success', 'warning', 'default')
size string 'medium' Switch size ('small' or 'medium')
disabled boolean false Disable the switch
required boolean false Mark the field as required
onChange function - Custom change handler with context data
onBlur function - Custom blur handler
helperText string - Helper text to display below the switch
error boolean false Error state of the switch
className string - Custom class name for the root element
sx SxProps<Theme> - The system prop that allows defining system overrides as well as additional CSS styles

Common Props (from FieldProps & SwitchProps)

Prop Type Required Description
name string Yes Field name in Formik values
label string No Field label
helperText string No Custom helper text
error boolean No Error state (auto-managed by Formik)
disabled boolean No Disabled state
required boolean No Required field indicator
Other SwitchProps No All Material-UI Switch props are supported

Examples

Basic Switch

<FormSwitch
  label="Enable Dark Mode"
  checked={darkModeEnabled}
  onChange={(e, checked) => setDarkModeEnabled(checked)}
  color="secondary"
  size="small"
/>

Switch with Formik

<Formik
  initialValues={{
    notifications: false,
    darkMode: true,
    autoSave: false,
  }}
  onSubmit={values => console.log('Form values:', values)}
>
  <Form>
    <Field
      component={FormSwitch}
      name="notifications"
      label="Enable Notifications"
      helperText="Receive email notifications"
      color="primary"
    />

    <Field
      component={FormSwitch}
      name="darkMode"
      label="Dark Mode"
      helperText="Use dark theme"
      color="secondary"
      labelPlacement="start"
    />

    <Field
      component={FormSwitch}
      name="autoSave"
      label="Auto Save"
      helperText="Automatically save changes"
      color="success"
      size="small"
    />

    <Button type="submit" variant="contained" color="primary">
      Save Settings
    </Button>
  </Form>
</Formik>

Custom Styled Switch

<FormSwitch
  label="Custom Styled Switch"
  checked={false}
  onChange={(e, checked) => console.log('Switch toggled:', checked)}
  className="custom-switch-class"
  color="warning"
  labelPlacement="top"
  helperText="This is a custom styled switch"
/>

Switch with Custom Change Handler

<Field
  component={FormSwitch}
  name="advancedMode"
  label="Advanced Mode"
  onChange={(e, checked, context) => {
    console.log('Field name:', context.fieldName);
    console.log('Formik value:', context.formikValue);
    // Custom logic here
  }}
  helperText="Enable advanced features"
/>

Switch with Validation

<Formik
  initialValues={{ termsAccepted: false }}
  validate={values => {
    const errors = {};
    if (!values.termsAccepted) {
      errors.termsAccepted = 'You must accept the terms to continue';
    }
    return errors;
  }}
  onSubmit={values => console.log(values)}
>
  <Form>
    <Field
      component={FormSwitch}
      name="termsAccepted"
      label="I accept the terms and conditions"
      helperText="Please read and accept the terms"
      required
    />

    <Button type="submit" variant="contained" color="primary">
      Continue
    </Button>
  </Form>
</Formik>

FormDateTextField

A versatile date input field component that provides a text-based date picker with Formik integration and Material-UI styling.

Features

  • Formik Integration: Seamlessly works with Formik for form state management
  • Material-UI Styling: Consistent look and feel with Material Design
  • Flexible Date Formatting: Supports custom date formats using day.js
  • TypeScript Support: Fully typed component with proper type definitions
  • Responsive Design: Works well across different screen sizes
  • Accessibility: Built with accessibility in mind

Available Date Formats

The component uses predefined date format constants from date.ts:

FORM_DATE_FORMAT

export const FORM_DATE_FORMAT = {
  short: 'YYYY-MM-DD',
  long: 'MM/DD/YYYY hh:mm A',
  custom: 'DD MMMM YYYY hh:mm A',
};

DATE_PICKER_DATE_FORMAT

export const DATE_PICKER_DATE_FORMAT = {
  short: 'DD/MM/YYYY',
};

DATE_PICKER_MONTH_YEAR_FORMAT

export const DATE_PICKER_MONTH_YEAR_FORMAT = {
  short: 'MM/YYYY',
  long: 'MMMM YYYY',
};

Basic Usage

import { Formik, Field } from 'formik';
import { FormDateTextField } from 'form-input-fields';

<Formik initialValues={{ eventDate: '' }} onSubmit={values => console.log(values)}>
  <Field component={FormDateTextField} name="eventDate" label="Event Date" format="MM/DD/YYYY" />
</Formik>;

Props

The FormDateTextField component accepts all props from FormDateTextFieldProps, FieldProps (Formik), and Material-UI's TextFieldProps (with some exclusions).

FormDateTextFieldProps Interface

Prop Type Default Description
format string FORM_DATE_FORMAT.long Date format string using day.js tokens
required boolean false Whether the field is required
disabled boolean false Whether the field is disabled
className string - Custom class name for the root element
helperText string - Helper text to display below the field
error boolean - Error state of the field
onChange (value: Dayjs | null) => void - Custom change handler
onBlur (event: React.FocusEvent<HTMLInputElement>) => void - Custom blur handler
sx SxProps<Theme> - The system prop that allows defining system overrides as well as additional CSS styles

Common Props (from FieldProps & TextFieldProps)

Prop Type Required Description
name string Yes Field name in Formik values
label string No Label for the input field
placeholder string No Placeholder text
fullWidth boolean No If true, the input will take up the full width of its container
margin 'none' | 'dense' | 'normal' No If 'dense' or 'normal', will adjust vertical spacing
size 'small' | 'medium' No The size of the text field

Examples

Basic Date Text Input

<FormDateTextField
  name="birthDate"
  label="Birth Date"
  format="YYYY-MM-DD"
  helperText="Enter your date of birth"
  required
/>

Date Text Field with Formik

import { Formik, Form, Field } from 'formik';
import { FormDateTextField, FormTextField } from 'form-input-fields';
import { Button } from '@mui/material';

const EventForm = () => (
  <Formik
    initialValues={{
      eventName: '',
      eventDate: '',
    }}
    onSubmit={values => {
      console.log('Form submitted:', values);
    }}
  >
    {({ isSubmitting }) => (
      <Form>
        <Field
          name="eventName"
          label="Event Name"
          component={FormTextField}
          fullWidth
          margin="normal"
        />

        <Field
          component={FormDateTextField}
          name="eventDate"
          label="Event Date"
          format="MM/DD/YYYY"
          required
          helperText="Select the event date"
          margin="normal"
        />

        <Button type="submit" variant="contained" color="primary" disabled={isSubmitting}>
          Submit
        </Button>
      </Form>
    )}
  </Formik>
);

Custom Date Format

<FormDateTextField
  name="appointmentTime"
  label="Appointment Time"
  format="dddd, MMMM D, YYYY h:mm A"
  helperText="Example: Monday, January 1, 2023 2:30 PM"
  required
/>

Disabled State

<FormDateTextField
  name="purchaseDate"
  label="Purchase Date"
  value="2023-05-15"
  disabled
  helperText="This field cannot be modified"
/>

With Error State

<FormDateTextField
  name="expiryDate"
  label="Expiry Date"
  error={!!errors.expiryDate && touched.expiryDate}
  helperText={touched.expiryDate && errors.expiryDate}
  format="MM/DD/YYYY"
  required
/>

FormMaskField

A flexible form field component with advanced text masking capabilities.

Features

  • Material-UI Integration: Consistent styling with other form components
  • Formik Integration: Seamless form state management
  • Flexible Masking: Pattern-based input masking with multiple character types
  • Uppercase Conversion: Automatic text transformation
  • TypeScript Support: Full type safety and IntelliSense
  • Clean Value Option: Return masked or unmasked values to form state

Usage with Formik

import { Formik, Field } from 'formik';
import { FormMaskField } from 'form-input-fields';

<Formik initialValues={{ phoneNumber: '', gameCode: '' }} onSubmit={values => console.log(values)}>
  <Field
    component={FormMaskField}
    name="phoneNumber"
    label="Phone Number"
    mask="(999) 999-9999"
    placeholder="Enter phone number"
  />

  <Field
    component={FormMaskField}
    name="gameCode"
    label="Game Code"
    mask="AAAAA"
    toUpperCase={true}
    returnCleanValue={true}
  />
</Formik>;

Mask Pattern Characters

Character Description Example
9 Digit (0-9) 999-99-9999 for SSN
A Letter (a-z, A-Z) AAA for country code
* Alphanumeric (a-z, A-Z, 0-9) ***-*** for mixed code
a Lowercase letter (a-z) aaa for lowercase only
Z Uppercase letter (A-Z) ZZZ for uppercase only
# Hexadecimal (0-9, A-F, a-f) ###### for hex color
Any other Literal character -, (, ), /, etc.

Props

Prop Type Default Description
mask string - Mask pattern using the characters above
placeholderChar string '_' Character shown in placeholder for mask positions
toUpperCase boolean false Convert input to uppercase automatically
returnCleanValue boolean false Return unmasked value to Formik (true) or masked value (false)
showMaskPattern boolean false Show the mask pattern as helper text below the input field
showPlaceholder boolean false Show placeholder text with mask pattern in the input field
onChange function - Custom change handler with masked, clean, and raw values
variant `'standard' 'outlined' 'filled'`
sx SxProps<Theme> - The system prop that allows defining system overrides as well as additional CSS styles

Plus all standard Material-UI TextField props and Formik FieldProps.

FormMaskFieldProps Interface

Prop Type Default Description
mask string - Mask pattern using the characters above
placeholderChar string '_' Character shown in placeholder for mask positions
toUpperCase boolean false Convert input to uppercase automatically
returnCleanValue boolean false Return unmasked value to Formik (true) or masked value (false)
showMaskPattern boolean false Show the mask pattern as helper text below the input field
showPlaceholder boolean false Show placeholder text with mask pattern in the input field
onChange function - Custom change handler with masked, clean, and raw values
variant `'standard' 'outlined' 'filled'`
sx SxProps<Theme> - The system prop that allows defining system overrides as well as additional CSS styles

Examples

Phone Number

<Field
  component={FormMaskField}
  name="phone"
  label="Phone Number"
  mask="(999) 999-9999"
  placeholder="(555) 123-4567"
  variant="outlined" // <-- Example with outlined variant
/>

Date Input

<Field
  component={FormMaskField}
  name="date"
  label="Date"
  mask="99/99/9999"
  placeholder="MM/DD/YYYY"
/>

Product Code (Uppercase)

<Field
  component={FormMaskField}
  name="productCode"
  label="Product Code"
  mask="AAA-999-AAA"
  toUpperCase={true}
  returnCleanValue={true}
/>

Credit Card

<Field
  component={FormMaskField}
  name="creditCard"
  label="Credit Card"
  mask="9999 9999 9999 9999"
  placeholder="1234 5678 9012 3456"
/>

Custom Change Handler

<Field
  component={FormMaskField}
  name="customField"
  label="Custom Field"
  mask="999-AAA"
  onChange={event => {
    console.log('Masked value:', event.target.value);
    console.log('Clean value:', event.target.cleanValue);
    console.log('Raw input:', event.target.rawValue);
  }}
  variant="outlined" // <-- Example with outlined variant
/>

Show Mask Pattern

<Field
  component={FormMaskField}
  name="gameCode"
  label="Game Code"
  mask="AAA-999"
  showMaskPattern={true}
  toUpperCase={true}
/>
// This will show "Pattern: AAA-999" as helper text below the input

Show Placeholder

<Field
  component={FormMaskField}
  name="phoneNumber"
  label="Phone Number"
  mask="(999) 999-9999"
  showPlaceholder={true}
/>
// This will show "(___) ___-____" as placeholder text in the input field

Complete Example Application

Here's a comprehensive example showing how to build a complete form application using FormMaskField with Material-UI and Formik:

App.tsx

import React from 'react';
import { Formik, Form, Field, FormikHelpers, FormikErrors } from 'formik';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { Grid } from '@mui/material';
import Paper from '@mui/material/Paper';
import Alert from '@mui/material/Alert';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { FormMaskField } from 'form-input-fields';
import './App.css';

interface FormValues {
  phone: string;
  date: string;
  creditCard: string;
  licensePlate: string;
  hexColor: string;
  customCode: string;
  socialSecurity: string;
  postalCode: string;
}

interface FormFieldEvent extends Omit<React.ChangeEvent<HTMLInputElement>, 'target'> {
  target: HTMLInputElement & {
    value: string;
    cleanValue: string;
    rawValue: string;
    name: string;
  };
}

// Create a Material-UI theme
const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
    secondary: {
      main: '#dc004e',
    },
  },
});

// Validation schema
const validateForm = (values: FormValues): FormikErrors<FormValues> => {
  const errors: Partial<FormValues> = {};

  if (!values.phone) {
    errors.phone = 'Phone number is required';
  } else if (values.phone.replace(/\D/g, '').length < 10) {
    errors.phone = 'Phone number must be 10 digits';
  }

  if (!values.date) {
    errors.date = 'Date is required';
  }

  if (!values.creditCard) {
    errors.creditCard = 'Credit card is required';
  } else if (values.creditCard.replace(/\D/g, '').length < 16) {
    errors.creditCard = 'Credit card must be 16 digits';
  }

  if (!values.licensePlate) {
    errors.licensePlate = 'License plate is required';
  }

  return errors;
};

function App() {
  const initialValues: FormValues = {
    phone: '',
    date: '',
    creditCard: '',
    licensePlate: '',
    hexColor: '',
    customCode: '',
    socialSecurity: '',
    postalCode: '',
  };

  const handleSubmit = (values: FormValues, { setSubmitting }: FormikHelpers<FormValues>) => {
    console.log('Form Values:', values);
    setTimeout(() => {
      alert('Form submitted! Check console for values.');
      setSubmitting(false);
    }, 400);
  };

  const handleCustomChange = (fieldName: keyof FormValues) => (event: FormFieldEvent) => {
    console.log(`${fieldName} changed:`, {
      masked: event.target.value,
      clean: event.target.cleanValue,
      raw: event.target.rawValue,
    });
    return event;
  };

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Container maxWidth="lg" sx={{ py: 4 }}>
        <Typography variant="h3" component="h1" gutterBottom align="center">
          FormMaskField Demo
        </Typography>

        <Typography variant="subtitle1" align="center" color="text.secondary" paragraph>
          A comprehensive example showcasing the FormMaskField component with various mask patterns
          and configurations
        </Typography>

        <Formik initialValues={initialValues} validate={validateForm} onSubmit={handleSubmit}>
          {({ values, isSubmitting, errors, touched }) => (
            <Form>
              <Grid container spacing={3}>
                {/* Basic Masks Section */}
                <Grid>
                  <Paper elevation={2} sx={{ p: 3 }}>
                    <Typography variant="h5" gutterBottom>
                      Basic Input Masks
                    </Typography>

                    <Grid container spacing={2}>
                      <Grid>
                        <Field
                          name="phone"
                          component={FormMaskField}
                          label="Phone Number"
                          mask="(999) 999-9999"
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="US phone number format"
                          onChange={handleCustomChange('phone')}
                          variant="outlined" // <-- Example with outlined variant
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="date"
                          component={FormMaskField}
                          label="Date"
                          mask="99/99/9999"
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="MM/DD/YYYY format"
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="socialSecurity"
                          component={FormMaskField}
                          label="Social Security Number"
                          mask="999-99-9999"
                          showMaskPattern={true}
                          showPlaceholder={true}
                          returnCleanValue={true}
                          helperText="Clean value returned (no dashes)"
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="postalCode"
                          component={FormMaskField}
                          label="ZIP Code"
                          mask="99999-9999"
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="US ZIP+4 format"
                        />
                      </Grid>
                    </Grid>
                  </Paper>
                </Grid>

                {/* Advanced Masks Section */}
                <Grid>
                  <Paper elevation={2} sx={{ p: 3 }}>
                    <Typography variant="h5" gutterBottom>
                      Advanced Input Masks
                    </Typography>

                    <Grid container spacing={2}>
                      <Grid>
                        <Field
                          name="creditCard"
                          component={FormMaskField}
                          label="Credit Card Number"
                          mask="9999-9999-9999-9999"
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="16-digit credit card number"
                          onChange={handleCustomChange('creditCard')}
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="licensePlate"
                          component={FormMaskField}
                          label="License Plate"
                          mask="AAA-999"
                          toUpperCase={true}
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="3 letters + 3 numbers (auto uppercase)"
                          onChange={handleCustomChange('licensePlate')}
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="hexColor"
                          component={FormMaskField}
                          label="Hex Color Code"
                          mask="#######"
                          toUpperCase={true}
                          showMaskPattern={true}
                          showPlaceholder={true}
                          placeholderChar="0"
                          helperText="6-digit hex color code"
                        />
                      </Grid>

                      <Grid>
                        <Field
                          name="customCode"
                          component={FormMaskField}
                          label="Custom Code"
                          mask="**-999-AA"
                          toUpperCase={true}
                          returnCleanValue={true}
                          showMaskPattern={true}
                          showPlaceholder={true}
                          helperText="Alphanumeric + digits + letters"
                          onChange={handleCustomChange('customCode')}
                        />
                      </Grid>
                    </Grid>
                  </Paper>
                </Grid>

                {/* Current Values Display */}
                <Grid>
                  <Paper elevation={2} sx={{ p: 3 }}>
                    <Typography variant="h5" gutterBottom>
                      Current Form Values
                    </Typography>

                    <Box sx={{ mt: 2 }}>
                      <Typography
                        variant="body2"
                        component="pre"
                        sx={{
                          backgroundColor: '#f5f5f5',
                          p: 2,
                          borderRadius: 1,
                          overflow: 'auto',
                          fontSize: '0.875rem',
                        }}
                      >
                        {JSON.stringify(values, null, 2)}
                      </Typography>
                    </Box>
                  </Paper>
                </Grid>

                {/* Form Errors Display */}
                {Object.keys(errors).length > 0 && Object.keys(touched).length > 0 && (
                  <Grid>
                    <Alert severity="error">
                      <Typography variant="h6" gutterBottom>
                        Form Validation Errors:
                      </Typography>
                      <ul>
                        {Object.entries(errors).map(
                          ([field, error]) =>
                            touched[field] && (
                              <li key={field}>
                                <strong>{field}:</strong> {error}
                              </li>
                            ),
                        )}
                      </ul>
                    </Alert>
                  </Grid>
                )}

                {/* Submit Button */}
                <Grid>
                  <Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>
                    <Button
                      type="submit"
                      variant="contained"
                      size="large"
                      disabled={isSubmitting}
                      sx={{ minWidth: 200 }}
                    >
                      {isSubmitting ? 'Submitting...' : 'Submit Form'}
                    </Button>
                  </Box>
                </Grid>
              </Grid>
            </Form>
          )}
        </Formik>
      </Container>
    </ThemeProvider>
  );
}

export default App;

App.css

#root {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}

.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}

.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}

.logo.react:hover {
  filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: no-preference) {
  a:nth-of-type(2) .logo {
    animation: logo-spin infinite 20s linear;
  }
}

.card {
  padding: 2em;
}

.read-the-docs {
  color: #888;
}

Key Features Demonstrated

This example application showcases:

  1. Complete Form Integration: Full Formik integration with validation and error handling
  2. Multiple Mask Types: Phone numbers, dates, credit cards, license plates, hex colors, and custom codes
  3. Advanced Features:
    • Uppercase conversion (toUpperCase)
    • Clean value return (returnCleanValue)
    • Custom placeholder characters (placeholderChar)
    • Pattern display (showMaskPattern)
    • Placeholder display (showPlaceholder)
  4. Custom Event Handling: onChange handlers that provide masked, clean, and raw values
  5. Material-UI Integration: Consistent styling with Material-UI theme and components
  6. Real-time Validation: Form validation with error display
  7. Live Value Display: Real-time display of current form values
  8. Responsive Layout: Grid-based responsive layout

Running the Example

To run this example:

  1. Install dependencies: npm install
  2. Start the development server: npm run dev
  3. Open your browser and navigate to the local development URL
  4. Interact with the form fields to see the masking in action
  5. Open browser console to see custom onChange event data

The example demonstrates how FormMaskField seamlessly integrates with existing Material-UI and Formik workflows while providing powerful input masking capabilities.

Support

If you like my work, you can support me here:

Buy Me a book

Testing

This package includes comprehensive test coverage for all form controls, ensuring reliability and proper functionality. Tests are written using Jest and React Testing Library.

Test Coverage

  • FormTextField: 100+ test cases covering basic rendering, input handling, Formik integration, error handling, accessibility, and sx prop support
  • FormDropDownField: Complete test suite for dropdown functionality, validation, and styling
  • FormDateField: Tests for date picker integration, validation, and formatting
  • FormDateTextField: Text-based date input testing with various formats
  • FormMaskField: Extensive masking functionality tests including pattern validation and custom handlers
  • FormCheckboxField: Checkbox state management and Formik integration tests
  • FormSwitch: Switch component testing with various configurations

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

# Run tests in debug mode
npm run test:debug

History

2025-11-10 - Enhanced Styling Support and Standardized Form Controls

Added sx prop support to all form controls

All form controls now support the sx prop for custom styling, providing a powerful and flexible way to apply styles directly to your form components:

  • FormTextField
  • FormCheckboxField
  • FormDateField
  • FormDateTextField
  • FormDropDownField
  • FormMaskField
  • FormSwitch

The sx prop follows Material-UI's sx system, allowing you to use CSS properties, theme values, and responsive design patterns.

Standardized FormControl wrapper pattern

All form controls now use a standardized FormControl wrapper pattern, ensuring consistent behavior, accessibility, and styling across all form components. This provides:

  • Consistent structure across all form controls
  • Improved accessibility with proper labeling and ARIA attributes
  • Unified error display and management
  • Better integration with Material-UI's styling system
  • Enhanced Formik form state management

Added variant prop to controls

The following controls now accept a variant prop ('standard' | 'outlined' | 'filled'), which is passed to the underlying MUI TextField. The default is 'standard':

  • FormTextField
  • FormDropDownField
  • FormMaskField

This allows you to easily switch between Material-UI's standard, outlined, and filled input styles for these components.


Styling Form Controls

sx Prop Support

All form controls now support the sx prop for custom styling, providing a powerful and flexible way to apply styles directly to your form components. The sx prop follows Material-UI's sx system, allowing you to use CSS properties, theme values, and responsive design patterns.

Benefits of the sx Prop

  • Direct Styling: Apply styles without creating separate CSS files or styled components
  • Theme Integration: Access to your Material-UI theme values (colors, spacing, breakpoints)
  • Responsive Design: Easily apply different styles at different breakpoints
  • Dynamic Styling: Use conditional styling based on component state or props
  • Performance: Optimized style application by Material-UI

Using the sx Prop with Form Controls

import { Formik, Field } from 'formik';
import { FormTextField, FormDropDownField, FormSwitch } from 'form-input-fields';

// Basic sx prop usage
<Field
  component={FormTextField}
  name="username"
  label="Username"
  sx={{
    backgroundColor: 'background.paper',
    borderRadius: 2,
    '& .MuiOutlinedInput-root': {
      '& fieldset': {
        borderColor: 'primary.main',
      },
    },
  }}
/>

// Responsive styling with sx
<Field
  component={FormDropDownField}
  name="category"
  label="Category"
  items={categories}
  sx={{
    width: { xs: '100%', md: '50%' },
    mx: { xs: 0, md: 2 },
  }}
/>

// Conditional styling with sx
<Field
  component={FormSwitch}
  name="notifications"
  label="Enable Notifications"
  sx={{
    '& .MuiSwitch-switchBase.Mui-checked': {
      color: 'success.main',
    },
    '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
      backgroundColor: 'success.main',
    },
  }}
/>

FormControl Wrapper Pattern

All form controls now use a standardized FormControl wrapper pattern, ensuring consistent behavior, accessibility, and styling across all form components. This pattern provides:

  • Consistent Structure: All form controls follow the same DOM structure
  • Accessibility: Proper labeling and ARIA attributes
  • Error Handling: Consistent error display and management
  • Styling Integration: Seamless integration with Material-UI's styling system

FormControl Wrapper Benefits

  1. Consistent Labeling: All controls properly associate labels with form inputs
  2. Error State Management: Unified error display and styling
  3. Helper Text: Consistent helper text positioning and styling
  4. Form Integration: Better integration with Formik's form state management
  5. Accessibility: Improved screen reader support and keyboard navigation

Example: FormControl Wrapper in Action

// Before (inconsistent structure)
<div className="custom-field">
  <label>Field Label</label>
  <input />
  <span className="error">Error message</span>
</div>

// After (standardized FormControl wrapper)
<FormControl
  error={hasError}
  fullWidth
  variant="outlined"
  sx={{ mb: 2 }}
>
  <InputLabel htmlFor="field-id">Field Label</InputLabel>
  <Field
    component={FormTextField}
    id="field-id"
    name="fieldName"
    label="Field Label"
  />
  <FormHelperText>{hasError ? errorMessage : helperText}</FormHelperText>
</FormControl>

Advanced Styling Examples

Custom Theme Integration

import { useTheme } from '@mui/material/styles';

function ThemedForm() {
  const theme = useTheme();

  return (
    <Field
      component={FormTextField}
      name="customField"
      label="Custom Styled Field"
      sx={{
        // Using theme values
        backgroundColor: theme.palette.grey[50],
        borderColor: theme.palette.primary.main,

        // Hover effects
        '&:hover': {
          backgroundColor: theme.palette.grey[100],
        },

        // Focus styles
        '& .Mui-focused': {
          borderColor: theme.palette.secondary.main,
        },

        // Custom styles for different states
        '&.Mui-error': {
          borderColor: theme.palette.error.main,
        },
      }}
    />
  );
}

Responsive Form Layout

<Box sx={{ display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap: 2 }}>
  <Field
    component={FormTextField}
    name="firstName"
    label="First Name"
    sx={{
      flex: 1,
      // Mobile-first responsive design
      minWidth: { xs: '100%', sm: 200 },
    }}
  />

  <Field
    component={FormTextField}
    name="lastName"
    label="Last Name"
    sx={{
      flex: 1,
      minWidth: { xs: '100%', sm: 200 },
    }}
  />
</Box>

Conditional Styling Based on State

<Field
  component={FormSwitch}
  name="premiumFeature"
  label="Enable Premium Features"
  sx={{
    // Style based on checked state
    '& .MuiSwitch-switchBase': {
      color: theme => (premiumEnabled ? theme.palette.success.main : 'default'),
    },

    // Animation for state changes
    transition: 'all 0.3s ease',

    // Custom styling when disabled
    '&.Mui-disabled': {
      opacity: 0.6,
    },
  }}
/>

Best Practices for Styling Form Controls

  1. Use Theme Values: Always prefer theme values over hardcoded colors and sizes
  2. Responsive Design: Use breakpoints to ensure your forms work on all screen sizes
  3. Consistent Spacing: Use the spacing scale for margins and padding
  4. Accessibility: Ensure color contrast and focus states are properly styled
  5. Performance: Avoid overly complex selectors in the sx prop for better performance

Migration Guide

If you're upgrading from a previous version, here's how to migrate to the new styling system:

Old Approach (Custom CSS Classes)

// Before
<Field component={FormTextField} name="username" className="custom-text-field" label="Username" />
/* In your CSS file */
.custom-text-field {
  background-color: #f5f5f5;
  border-radius: 8px;
}

.custom-text-field .MuiOutlinedInput-root {
  border-color: #1976d2;
}

New Approach (sx Prop)

// After
<Field
  component={FormTextField}
  name="username"
  label="Username"
  sx={{
    backgroundColor: 'background.paper',
    borderRadius: 2,
    '& .MuiOutlinedInput-root': {
      '& fieldset': {
        borderColor: 'primary.main',
      },
    },
  }}
/>

The new approach provides better theme integration, responsive design capabilities, and improved maintainability.