input-states-react
v1.0.29
Published
Reusable UI components for forms and steps
Downloads
94
Maintainers
Readme
React + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel for Fast Refresh.
- @vitejs/plugin-react-swc uses SWC for Fast Refresh.
Usage https://charming-halva-08cda7.netlify.app/
DemoForm https://courageous-phoenix-da7ceb.netlify.app/
BaseForm – Dynamic Multi-step React Form
BaseForm is a React component that enables dynamic multi-step form creation based on a JSON config.
Ideal for use cases like insurance applications, financial product forms, or lead collection with validation steps.
Features
- Define form fields and steps dynamically via JSON config
- Supports various input types: Radio, Number, Email, Checkbox, Label, Text
- Built-in Stepper with Next/Prev/Submit flow
- Fetch summary data from API (e.g., premium or plan summary)
- Customizable button text and labels per step
- Works seamlessly with Tailwind CSS or custom CSS
Installation
npm install input-states-reactThen build if needed:
npm install
npm run buildUsage
1. Import Component & Styles
import { BaseForm } from "input-states-react";
import "input-states-react/dist/input-states-react.css";2. Create a JSON Config
const formConfig = {
planDataApiUrl: "https://www.idinrice.com/api/plan-data.php",
fields: [
{
name: "gender",
component: "RadioGroup",
props: {
head: "What is your gender?",
name: "gender",
options: [
{ label: "Male", value: "M" },
{ label: "Female", value: "F" }
],
direction: "horizontal"
},
errorMessage: "Please select gender"
},
{
name: "age",
component: "NumericTextInput",
props: {
head: "How old are you?",
label: "Age",
suggest: "1-120",
min: 1,
max: 120,
maxDigit: 3,
required: true
},
errorMessage: "Age must be between 1-120 years"
}
],
steps: [
{ name: "Applicant Info", buttonLabel: "Get Recommendation" },
{
name: "Additional Info",
buttonLabel: "View Your Plan and Premium",
insurancePlanHtml: "<div>...HTML...</div>",
warning: "Warning: Please review your information before submission."
},
{
name: "Summary & Confirmation",
planTitle: "Be Together Infinite 789",
items: [
{ label: "Sum Insured", valueKey: "sumInsured", unit: "THB" }
],
premium: {
label: "Your Premium",
valueKey: "premiumValue",
unit: "THB/year"
},
planDetailLink: {
url: "https://www.idinrice.com?planDetailLink=7070",
label: "View BT Infinite 789 Details",
desc: "For more information on benefits and coverage, visit:"
},
company: "Underwritten by AIA Co., Ltd.",
notice: "Please read the terms and conditions carefully before applying.",
buttonLabel: "Schedule a Consultation",
dropLeadFormUrl: "https://www.idinrice.com?dropLeadFormUrl=7070"
}
]
};3. Render BaseForm in Your Component
import React, { useState } from "react";
import { BaseForm } from "input-states-react";
import "input-states-react/dist/input-states-react.css";
import { getInitialFormData, mapFieldComponents } from "input-states-react";
const formConfig = {
planDataApiUrl: "https://www.idinrice.com/api/plan-data.php",
// PremiumPaymentPeriodYears: "8,12,16",
fieds: [
{
name: "gender",
component: "RadioGroup",
props: {
head: "คุณเป็น",
name: "gender",
options: [
{ label: "ชาย", value: "M" },
{ label: "หญิง", value: "F" },
],
direction: "horizontal",
},
errorMessage: "กรุณาเลือกเพศ",
},
{
name: "age",
component: "NumericTextInput",
props: {
head: "ปัจจุบันคุณอายุเท่าไหร่",
label: "อายุ",
suggest: "1-120",
min: 1,
max: 120,
maxDigit: 3,
required: true,
},
errorMessage: "อายุต้องอยู่ระหว่าง 1-120 ปี",
},
{
name: "coverage",
component: "NumericTextInput",
props: {
head: "ทุนประกันภัย* ที่คุณต้องการ",
label: "ทุนประกัน",
suggest: "100,000 - 1,000,000",
min: 100000,
max: 1000000,
maxDigit: 7,
decimalPlaces: 2,
required: true,
},
errorMessage: "ทุนประกันภัยต้องอยู่ระหว่าง 100,000 ถึง 1,000,000 บาท",
},
{
name: "coverageNote",
component: "StandardLabel", // display-only components (e.g. StandardLabel, HeadText, Footer) skip validation
props: {
html: "<b>*หมายเหตุ:</b> กรุณาอ่านให้ครบถ้วนก่อนดำเนินการต่อ",
},
},
{
name: "email",
component: "EmailInput",
props: {
head: "รบกวนกรอกอีเมลเพื่อรับแผนประกันและค่าเบี้ยของคุณ",
label: "อีเมล",
required: true,
},
errorMessage: "กรุณากรอกอีเมลที่ถูกต้อง",
},
{
name: "consent",
component: "ConsentCheckbox",
props: {
children: ` <div>
<div>
<p class="text-default editor">
เบี้ยประกันชีวิตเริ่มต้นที่ <b>89,900 บาทต่อปี*</b> สำหรับความคุ้มครอง 100,000 บาท
<br />
กรมธรรม์นี้ออกแบบมาเพื่อช่วยให้คุณและคนที่คุณรักสร้างความมั่งคั่งอย่างมั่นใจ
</p>
<h2 style="margin-top: 32px;">
กรมธรรม์นี้ออกแบบมาเพื่อช่วยให้คุณและคนที่คุณรักสร้างความมั่งคั่งอย่างมั่นใจ
</h2>
<div>
<b>ชำระเบี้ยเพียง 7 ปี</b>
<ol class="text-default editor" style="margin-top: 8px; margin-bottom: 0; padding-left: 20px;">
<li>คุ้มครองจนถึงวันครบรอบปีกรมธรรม์หลังผู้เอาประกันภัยอายุครบ 89 ปี</li>
<li>รับเงินคืนรายปี 9% หรือ 10% ของจำนวนเงินเอาประกันภัย</li>
<li>เมื่อครบสัญญา รับเงินครบสัญญา 789% ของจำนวนเงินเอาประกันภัย</li>
</ol>
</div>
<div style="margin: 24px 0 16px;">
<b>ความคุ้มครองกรณีเสียชีวิต:</b>
<ol class="text-default editor" style="margin-top: 8px; margin-bottom: 0; padding-left: 20px;">
<li>เริ่มต้นที่ 100% ของจำนวนเงินเอาประกันภัย และเพิ่มขึ้นปีละ 100% สูงสุด 789%</li>
<li>รับเงินเพิ่มกรณีเสียชีวิตจากอุบัติเหตุ (ADB2) อีก 100% ของจำนวนเงินเอาประกันภัย</li>
<li>สมัครง่าย ไม่ต้องตรวจสุขภาพ ไม่ต้องตอบคำถามสุขภาพ</li>
</ol>
</div>
<div style="margin-bottom: 12px;">โดยบริษัท เอไอเอ จำกัด</div>
<div style="margin-bottom: 24px;">
<b>หมายเหตุ:</b> *เบี้ยประกันคำนวณจากเพศหญิง อายุ 32 ปี สำหรับความคุ้มครอง 100,000 บาท อัตราเบี้ยอาจแตกต่างกันตามอายุและเพศ เงื่อนไขเป็นไปตามที่บริษัทและธนาคารกำหนด
<ol style="margin: 8px 0 8px 20px;">
<li>การคืนเงินจะได้รับตั้งแต่ปีกรมธรรม์แรก จนถึงปีที่ถัดจากผู้เอาประกันภัยมีอายุครบ 88 ปี ทั้งนี้ขึ้นอยู่กับแบบประกันที่เลือก</li>
<li>ความคุ้มครองกรณีเสียชีวิตจากอุบัติเหตุจะจ่ายตามความคุ้มครองหลักของกรมธรรม์</li>
</ol>
สำคัญ: โปรดศึกษาความคุ้มครองและเงื่อนไขก่อนตัดสินใจทำประกันภัย
</div>
<div class="text-default editor" style="display: flex; align-items: center; margin-top: 20px;">
<span style="margin-right: 12px;">รับประกันชีวิตโดย บริษัท เอไอเอ จำกัด</span>
<img
src="https://www.aia.co.th/content/dam/th-wise/images/system/icons/aia-logo-red.svg"
alt="AIA logo"
style="height: 50px;"
/>
</div>
</div>
</div>`,
},
errorMessage: "กรุณายินยอมก่อนดำเนินการต่อ",
},
{
name: "name",
component: "TextInput",
props: {
head: "กรอกข้อความที่ต้องการ",
label: "ข้อความ",
required: true,
},
errorMessage: "กรุณากรอกข้อความ",
},
],
steps: [
{
name: "ข้อมูลผู้ขอประกันภัย",
buttonLabel: "รับคำแนะนำ",
},
{
name: "ข้อมูลเพิ่มเติม",
buttonLabel: "ดูแผนและค่าเบี้ยของคุณ",
insurancePlanHtml: `
<div>
<div>
<p class="text-default editor">
เบี้ยประกันชีวิตเริ่มต้นที่ <b>89,900 บาทต่อปี*</b> สำหรับความคุ้มครอง 100,000 บาท
<br />
กรมธรรม์นี้ออกแบบมาเพื่อช่วยให้คุณและคนที่คุณรักสร้างความมั่งคั่งอย่างมั่นใจ
</p>
<h2 style="margin-top: 32px;">
กรมธรรม์นี้ออกแบบมาเพื่อช่วยให้คุณและคนที่คุณรักสร้างความมั่งคั่งอย่างมั่นใจ
</h2>
<div>
<b>ชำระเบี้ยเพียง 7 ปี</b>
<ol class="text-default editor" style="margin-top: 8px; margin-bottom: 0; padding-left: 20px;">
<li>คุ้มครองจนถึงวันครบรอบปีกรมธรรม์หลังผู้เอาประกันภัยอายุครบ 89 ปี</li>
<li>รับเงินคืนรายปี 9% หรือ 10% ของจำนวนเงินเอาประกันภัย</li>
<li>เมื่อครบสัญญา รับเงินครบสัญญา 789% ของจำนวนเงินเอาประกันภัย</li>
</ol>
</div>
<div style="margin: 24px 0 16px;">
<b>ความคุ้มครองกรณีเสียชีวิต:</b>
<ol class="text-default editor" style="margin-top: 8px; margin-bottom: 0; padding-left: 20px;">
<li>เริ่มต้นที่ 100% ของจำนวนเงินเอาประกันภัย และเพิ่มขึ้นปีละ 100% สูงสุด 789%</li>
<li>รับเงินเพิ่มกรณีเสียชีวิตจากอุบัติเหตุ (ADB2) อีก 100% ของจำนวนเงินเอาประกันภัย</li>
<li>สมัครง่าย ไม่ต้องตรวจสุขภาพ ไม่ต้องตอบคำถามสุขภาพ</li>
</ol>
</div>
<div style="margin-bottom: 12px;">โดยบริษัท เอไอเอ จำกัด</div>
<div style="margin-bottom: 24px;">
<b>หมายเหตุ:</b> *เบี้ยประกันคำนวณจากเพศหญิง อายุ 32 ปี สำหรับความคุ้มครอง 100,000 บาท อัตราเบี้ยอาจแตกต่างกันตามอายุและเพศ เงื่อนไขเป็นไปตามที่บริษัทและธนาคารกำหนด
<ol style="margin: 8px 0 8px 20px;">
<li>การคืนเงินจะได้รับตั้งแต่ปีกรมธรรม์แรก จนถึงปีที่ถัดจากผู้เอาประกันภัยมีอายุครบ 88 ปี ทั้งนี้ขึ้นอยู่กับแบบประกันที่เลือก</li>
<li>ความคุ้มครองกรณีเสียชีวิตจากอุบัติเหตุจะจ่ายตามความคุ้มครองหลักของกรมธรรม์</li>
</ol>
สำคัญ: โปรดศึกษาความคุ้มครองและเงื่อนไขก่อนตัดสินใจทำประกันภัย
</div>
<div class="text-default editor" style="display: flex; align-items: center; margin-top: 20px;">
<span style="margin-right: 12px;">รับประกันชีวิตโดย บริษัท เอไอเอ จำกัด</span>
<img
src="https://www.aia.co.th/content/dam/th-wise/images/system/icons/aia-logo-red.svg"
alt="AIA logo"
style="height: 50px;"
/>
</div>
</div>
</div>`,
warning:
"คำเตือน : ผู้ซื้อควรทำความเข้าใจในรายละเอียด ความคุ้มครองและเงื่อนไขก่อนตัดสินใจทำประกันภัยทุกครั้ง",
},
{
name: "สรุปและยืนยัน",
planTitle: "Be Together Infinite 789",
items: [
{ label: "ทุนประกันภัย", valueKey: "sumInsured", unit: "บาท" },
{
label: "รวมผลประโยชน์กรณีมีชีวิตอยู่จนครบสัญญา",
valueKey: "totalBenefit",
unit: "บาท",
},
{
label: "รับเงินเมื่อครบกำหนดสัญญา สิ้นปีที่ X",
valueKey: "maturityBenefit",
unit: "บาท",
},
{
label: "ความคุ้มครองชีวิต",
valueKey: "lifeCoverage",
unit: "บาท",
},
{ label: "รับเงินคืน", valueKey: "cashBack", unit: "บาท" },
{
label: "ณ สิ้นปีที่ X-X",
valueKey: "periodBenefit1",
unit: "บาท",
},
{
label: "ณ สิ้นปีที่ X-X",
valueKey: "periodBenefit2",
unit: "บาท",
},
],
premium: {
label: "เบี้ยประกันของคุณ", // <-- เพิ่ม label ตรงนี้!
valueKey: "premiumValue",
unit: "บาท/ปี",
},
planDetailLink: {
url: "https://www.idinrice.com?planDetailLink=7070",
label: "ดูรายละเอียด BT Infinite 789",
desc: "สามารถดูรายละเอียดตารางผลประโยชน์และความคุ้มครองเพิ่มเติมได้ที่",
},
company: "รับประกันชีวิตโดย บริษัท เอไอเอ จำกัด",
notice:
"คำเตือน : ผู้ซื้อควรทำความเข้าใจในรายละเอียด ความคุ้มครองและเงื่อนไข ก่อนตัดสินใจทำประกันภัยทุกครั้ง",
buttonLabel: "ทำนัดเพื่อรับคำปรึกษา",
dropLeadFormUrl:
"https://www.idinrice.com?planDetailLink=7070",
},
],
};
const rawFields = formConfig?.fieds || [];
// mapFieldComponents: เปลี่ยน string เป็น component ที่นำมาใช้จริง
const mappedFields = mapFieldComponents(rawFields);
const DemoForm = () => {
const [formData, setFormData] = useState({});
const handleSubmit = (validatedData) => {
alert("Form submitted:\n" + JSON.stringify(validatedData, null, 2));
};
const buttonLabel = formConfig.steps[0].buttonLabel;
return (
<BaseForm
fields={mappedFields}
onFormSubmitAndValidated={handleSubmit}
formData={formData}
setFormData={setFormData}
buttonLabel={buttonLabel}
/>
);
};
export default DemoForm;
