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

iam-auto-fills

v0.1.4

Published

Zero-config React button that auto-fills visible form fields with fake data

Readme

faker-btn

A zero-dependency React button component that auto-fills form fields with fake data. Works with React Hook Form, Formik, or plain HTML forms.

Features

  • Zero runtime dependencies — data comes from your own schema
  • Framework agnostic — adapters for React Hook Form & Formik included
  • Multi-step form support — auto-detects visible fields per step via DOM scan
  • Dev-only by default — hidden in production builds

Installation

npm install faker-btn

Quick Start

import { FakerButton } from 'faker-btn';

const schema = {
  firstName: ['John', 'Jane', 'Bob'],
  email: () => `user${Math.floor(Math.random() * 999)}@example.com`,
  city: ['New York', 'London', 'Tokyo'],
};

function MyForm() {
  return (
    <form>
      <input name="firstName" />
      <input name="email" />
      <input name="city" />
      <FakerButton schema={schema} />
    </form>
  );
}

Schema

A schema is a record mapping field names to either:

  • string[] — randomly picks one value from the array
  • () => string — calls the function to generate a value
import { FakerSchema } from 'faker-btn';

const schema: FakerSchema = {
  name: ['Alice', 'Bob', 'Charlie'],
  email: () => `test${Date.now()}@mail.com`,
  age: () => String(Math.floor(Math.random() * 50) + 18),
  gender: ['male', 'female'],
  phone: ['08123456789', '08567891234', '08219876543'],
  address: () => `Jl. Example No. ${Math.floor(Math.random() * 100)}`,
};

Nested schema

Schemas support nested objects — they are automatically flattened to dot notation (compatible with React Hook Form and Formik).

const schema: FakerSchema = {
  // Flat fields
  username: ['johndoe', 'janedoe'],

  // Nested fields → flattened to 'personal.firstName', 'personal.lastName', etc.
  personal: {
    firstName: ['John', 'Jane', 'Bob'],
    lastName: ['Smith', 'Doe', 'Johnson'],
    contact: {
      email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
      phone: ['08123456789', '08567891234'],
    },
  },

  // Nested address → 'address.street', 'address.city', 'address.zip'
  address: {
    street: ['Jl. Sudirman No. 1', 'Jl. Thamrin No. 5'],
    city: ['Jakarta', 'Bandung', 'Surabaya'],
    zip: ['10110', '40111', '60111'],
  },
};

You can also use dot notation directly if you prefer:

const schema: FakerSchema = {
  'personal.firstName': ['John', 'Jane'],
  'personal.lastName': ['Smith', 'Doe'],
  'address.city': ['Jakarta', 'Bandung'],
};

Usage with React Hook Form

Method 1: Using useFakerRHF hook

The simplest way. Pass your schema and setValue from useForm() — done.

import { useFakerRHF } from 'faker-btn';
import { useForm } from 'react-hook-form';

const schema = {
  firstName: ['John', 'Jane', 'Bob'],
  lastName: ['Smith', 'Doe', 'Johnson'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  phone: ['08123456789', '08567891234'],
  age: () => String(Math.floor(Math.random() * 40) + 18),
};

function RegistrationForm() {
  const {
    register,
    setValue,
    handleSubmit,
    formState: { errors },
  } = useForm();

  // Hook returns a fill function
  const fill = useFakerRHF(schema, setValue);

  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>First Name</label>
        <input {...register('firstName', { required: true })} />
        {errors.firstName && <span>Required</span>}
      </div>

      <div>
        <label>Last Name</label>
        <input {...register('lastName', { required: true })} />
      </div>

      <div>
        <label>Email</label>
        <input {...register('email', { required: true })} type="email" />
      </div>

      <div>
        <label>Phone</label>
        <input {...register('phone')} />
      </div>

      <div>
        <label>Age</label>
        <input {...register('age')} type="number" />
      </div>

      {/* Just call fill on click — all fields get populated + validated */}
      <button type="button" onClick={fill}>🎲 Fill Fake Data</button>
      <button type="submit">Submit</button>
    </form>
  );
}

Method 2: Using <FakerButton /> component with onFill

If you prefer a ready-made button component:

import { FakerButton } from 'faker-btn';
import { useForm } from 'react-hook-form';

const schema = {
  firstName: ['John', 'Jane'],
  lastName: ['Smith', 'Doe'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  password: () => `Pass${Math.random().toString(36).slice(2, 10)}!`,
};

function LoginForm() {
  const { register, setValue, handleSubmit } = useForm();

  return (
    <form onSubmit={handleSubmit(console.log)}>
      <input {...register('firstName')} placeholder="First Name" />
      <input {...register('lastName')} placeholder="Last Name" />
      <input {...register('email')} placeholder="Email" type="email" />
      <input {...register('password')} placeholder="Password" type="password" />

      <FakerButton
        schema={schema}
        onFill={(data) => {
          Object.entries(data).forEach(([key, value]) => {
            setValue(key, value, { shouldValidate: true });
          });
        }}
      />

      <button type="submit">Submit</button>
    </form>
  );
}

React Hook Form with validation schema (Zod/Yup)

Works the same way — shouldValidate: true triggers validation automatically:

import { useFakerRHF } from 'faker-btn';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const formSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  age: z.coerce.number().min(18).max(65),
});

const fakerSchema = {
  name: ['Alice Johnson', 'Bob Smith', 'Charlie Brown'],
  email: () => `user${Math.floor(Math.random() * 999)}@company.com`,
  age: () => String(Math.floor(Math.random() * 40) + 20),
};

function ValidatedForm() {
  const { register, setValue, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(formSchema),
  });

  const fill = useFakerRHF(fakerSchema, setValue);

  return (
    <form onSubmit={handleSubmit(console.log)}>
      <input {...register('name')} />
      {errors.name && <span>{errors.name.message}</span>}

      <input {...register('email')} />
      {errors.email && <span>{errors.email.message}</span>}

      <input {...register('age')} type="number" />
      {errors.age && <span>{errors.age.message}</span>}

      <button type="button" onClick={fill}>🎲 Fake</button>
      <button type="submit">Submit</button>
    </form>
  );
}

React Hook Form with Controller (controlled components)

When using Controller, native DOM events won't update React state — you must use useFakerRHF or onFill. The hook calls setValue directly which works with both register and Controller.

import { useFakerRHF } from 'faker-btn';
import { useForm, Controller } from 'react-hook-form';

const schema = {
  firstName: ['John', 'Jane', 'Bob'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  role: ['admin', 'editor', 'viewer'],
  bio: ['Software engineer', 'Designer', 'Product manager'],
};

function ControlledForm() {
  const { control, setValue, handleSubmit } = useForm();
  const fill = useFakerRHF(schema, setValue);

  return (
    <form onSubmit={handleSubmit(console.log)}>
      <Controller
        name="firstName"
        control={control}
        rules={{ required: 'First name is required' }}
        render={({ field, fieldState }) => (
          <div>
            <label>First Name</label>
            <input {...field} />
            {fieldState.error && <span>{fieldState.error.message}</span>}
          </div>
        )}
      />

      <Controller
        name="email"
        control={control}
        rules={{ required: 'Email is required' }}
        render={({ field, fieldState }) => (
          <div>
            <label>Email</label>
            <input {...field} type="email" />
            {fieldState.error && <span>{fieldState.error.message}</span>}
          </div>
        )}
      />

      <Controller
        name="role"
        control={control}
        render={({ field }) => (
          <div>
            <label>Role</label>
            <select {...field}>
              <option value="">Select role</option>
              <option value="admin">Admin</option>
              <option value="editor">Editor</option>
              <option value="viewer">Viewer</option>
            </select>
          </div>
        )}
      />

      <Controller
        name="bio"
        control={control}
        render={({ field }) => (
          <div>
            <label>Bio</label>
            <textarea {...field} rows={3} />
          </div>
        )}
      />

      {/* useFakerRHF works with Controller — it calls setValue internally */}
      <button type="button" onClick={fill}>🎲 Fill Fake Data</button>
      <button type="submit">Submit</button>
    </form>
  );
}

Note: For register (uncontrolled), <FakerButton schema={schema} /> alone works because it dispatches native DOM events. For Controller (controlled), always use useFakerRHF or pass onFill — DOM events won't reach React state.


Usage with Formik

Method 1: Using useFakerFormik hook

import { useFakerFormik } from 'faker-btn';
import { useFormik } from 'formik';
import * as Yup from 'yup';

const schema = {
  firstName: ['John', 'Jane', 'Bob'],
  lastName: ['Smith', 'Doe', 'Johnson'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  phone: ['08123456789', '08567891234', '08219876543'],
  address: () => `Jl. Contoh No. ${Math.floor(Math.random() * 100)}`,
};

const validationSchema = Yup.object({
  firstName: Yup.string().required('Required'),
  lastName: Yup.string().required('Required'),
  email: Yup.string().email('Invalid email').required('Required'),
  phone: Yup.string().required('Required'),
  address: Yup.string().required('Required'),
});

function ContactForm() {
  const formik = useFormik({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
      phone: '',
      address: '',
    },
    validationSchema,
    onSubmit: (values) => {
      console.log('Submitted:', values);
    },
  });

  // Pass schema + formik.setValues
  const fill = useFakerFormik(schema, formik.setValues);

  return (
    <form onSubmit={formik.handleSubmit}>
      <div>
        <label>First Name</label>
        <input
          name="firstName"
          value={formik.values.firstName}
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
        />
        {formik.touched.firstName && formik.errors.firstName && (
          <span>{formik.errors.firstName}</span>
        )}
      </div>

      <div>
        <label>Last Name</label>
        <input
          name="lastName"
          value={formik.values.lastName}
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
        />
      </div>

      <div>
        <label>Email</label>
        <input
          name="email"
          type="email"
          value={formik.values.email}
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
        />
      </div>

      <div>
        <label>Phone</label>
        <input
          name="phone"
          value={formik.values.phone}
          onChange={formik.handleChange}
        />
      </div>

      <div>
        <label>Address</label>
        <textarea
          name="address"
          value={formik.values.address}
          onChange={formik.handleChange}
        />
      </div>

      <button type="button" onClick={fill}>🎲 Fill Fake Data</button>
      <button type="submit">Submit</button>
    </form>
  );
}

Method 2: Using <FakerButton /> component with Formik

import { FakerButton } from 'faker-btn';
import { Formik, Form, Field } from 'formik';

const schema = {
  username: ['johndoe', 'janedoe', 'bobsmith'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  bio: ['Software developer', 'Designer', 'Product manager'],
};

function ProfileForm() {
  return (
    <Formik
      initialValues={{ username: '', email: '', bio: '' }}
      onSubmit={(values) => console.log(values)}
    >
      {({ setValues }) => (
        <Form>
          <Field name="username" placeholder="Username" />
          <Field name="email" type="email" placeholder="Email" />
          <Field name="bio" as="textarea" placeholder="Bio" />

          <FakerButton
            schema={schema}
            onFill={(data) => setValues(data, true)}
          />

          <button type="submit">Save</button>
        </Form>
      )}
    </Formik>
  );
}

Usage with plain HTML forms

Just drop <FakerButton schema={schema} /> inside a <form>. It dispatches native input and change events automatically — no onFill callback needed.

import { FakerButton } from 'faker-btn';

const schema = {
  name: ['Alice', 'Bob', 'Charlie'],
  email: () => `contact${Math.floor(Math.random() * 100)}@mail.com`,
  message: ['Hello!', 'I have a question', 'Please contact me'],
};

function ContactPage() {
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      const formData = new FormData(e.currentTarget);
      console.log(Object.fromEntries(formData));
    }}>
      <input name="name" placeholder="Your name" />
      <input name="email" type="email" placeholder="Your email" />
      <textarea name="message" placeholder="Your message" />

      {/* No onFill needed — native events are dispatched */}
      <FakerButton schema={schema} />

      <button type="submit">Send</button>
    </form>
  );
}

Multi-step forms

The component scans only visible fields in the DOM. For multi-step forms, it automatically fills only the fields shown in the current step.

Option 1: Single schema for all steps

import { FakerButton } from 'faker-btn';
import { useForm } from 'react-hook-form';
import { useState } from 'react';

const schema = {
  // Step 1 - Personal info
  firstName: ['John', 'Jane', 'Bob'],
  lastName: ['Smith', 'Doe', 'Johnson'],
  email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  // Step 2 - Address
  address: ['123 Main St', '456 Oak Ave', '789 Pine Rd'],
  city: ['Jakarta', 'Bandung', 'Surabaya'],
  zipCode: ['10110', '40111', '60111'],
  // Step 3 - Payment
  cardNumber: ['4111111111111111', '5500000000000004'],
  expiry: ['12/25', '06/26', '03/27'],
  cvv: ['123', '456', '789'],
};

function MultiStepForm() {
  const [step, setStep] = useState(1);
  const { register, setValue, handleSubmit } = useForm();

  return (
    <form onSubmit={handleSubmit(console.log)}>
      {step === 1 && (
        <div>
          <h3>Step 1: Personal Info</h3>
          <input {...register('firstName')} placeholder="First Name" />
          <input {...register('lastName')} placeholder="Last Name" />
          <input {...register('email')} placeholder="Email" />
        </div>
      )}

      {step === 2 && (
        <div>
          <h3>Step 2: Address</h3>
          <input {...register('address')} placeholder="Address" />
          <input {...register('city')} placeholder="City" />
          <input {...register('zipCode')} placeholder="Zip Code" />
        </div>
      )}

      {step === 3 && (
        <div>
          <h3>Step 3: Payment</h3>
          <input {...register('cardNumber')} placeholder="Card Number" />
          <input {...register('expiry')} placeholder="MM/YY" />
          <input {...register('cvv')} placeholder="CVV" />
        </div>
      )}

      {/* One button, one schema — only visible fields get filled per step */}
      <FakerButton
        schema={schema}
        onFill={(data) => {
          Object.entries(data).forEach(([k, v]) => setValue(k, v, { shouldValidate: true }));
        }}
      />

      {step > 1 && <button type="button" onClick={() => setStep(step - 1)}>Back</button>}
      {step < 3 && <button type="button" onClick={() => setStep(step + 1)}>Next</button>}
      {step === 3 && <button type="submit">Submit</button>}
    </form>
  );
}

Option 2: Schema per step

const schemas = {
  1: {
    firstName: ['John', 'Jane'],
    lastName: ['Smith', 'Doe'],
    email: () => `user${Math.floor(Math.random() * 999)}@mail.com`,
  },
  2: {
    address: ['123 Main St', '456 Oak Ave'],
    city: ['Jakarta', 'Bandung'],
    zipCode: ['10110', '40111'],
  },
  3: {
    cardNumber: ['4111111111111111'],
    expiry: ['12/25'],
    cvv: ['123'],
  },
};

// Pass only current step's schema
<FakerButton schema={schemas[currentStep]} onFill={...} />

API Reference

<FakerButton />

| Prop | Type | Default | Description | |------|------|---------|-------------| | schema | FakerSchema | required | Field names mapped to values | | onFill | (data: Record<string, string>) => void | — | Callback with generated data | | containerRef | RefObject<HTMLElement> | — | Scope DOM scan to container | | dispatchEvents | boolean | true | Dispatch native input/change events | | label | string | '🎲 Fake' | Button label | | className | string | — | Custom class | | style | CSSProperties | — | Custom style | | devOnly | boolean | true | Hide in production |

useFakerRHF(schema, setValue)

Hook for React Hook Form. Returns a () => Record<string, string> function that fills all fields and triggers validation.

const fill = useFakerRHF(schema, setValue);
// fill() → generates data, calls setValue for each field with { shouldValidate: true }

useFakerFormik(schema, setValues)

Hook for Formik. Returns a () => Record<string, string> function that fills all fields and triggers validation.

const fill = useFakerFormik(schema, formik.setValues);
// fill() → generates data, calls setValues(data, true)

generateFromSchema(schema)

Utility to generate data from a schema without any DOM interaction. Useful for testing or custom integrations.

import { generateFromSchema } from 'faker-btn';

const data = generateFromSchema({
  name: ['Alice', 'Bob'],
  email: () => '[email protected]',
});
// { name: 'Bob', email: '[email protected]' }

FakerSchema type

type FieldGenerator = string[] | (() => string);

interface FakerSchema {
  [key: string]: FieldGenerator | FakerSchema; // supports nested objects
}

Local development

# Build the package
npm run build

# Use locally in another project
cd /path/to/your-project
npm install ../path/to/faker-btn

License

MIT