iam-auto-fills
v0.1.4
Published
Zero-config React button that auto-fills visible form fields with fake data
Maintainers
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-btnQuick 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. ForController(controlled), always useuseFakerRHFor passonFill— 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-btnLicense
MIT
