@inverz/thai-input
v1.1.0
Published
React inputs for Thai data: national ID with checksum, phone numbers, money with baht text — plus validators that work without React
Readme
@inverz/thai-input
ช่องกรอกข้อมูลไทยสำหรับ React: เลขบัตรประชาชน / เลขผู้เสียภาษี (ตรวจ checksum), เบอร์โทร และ จำนวนเงิน (พร้อมคำอ่าน "บาทถ้วน") จัดรูปแบบให้ตอนพิมพ์ ตรวจความถูกต้องทันที และได้ค่าที่สะอาดไปใช้ต่อ มีฟังก์ชันตรวจสอบแยกให้ใช้ฝั่ง server โดยไม่ต้องมี React
React inputs for Thai national IDs (with checksum), phone numbers and money amounts (with Thai baht text), plus React-free validators for the server.
ติดตั้ง
npm i @inverz/thai-inputimport "@inverz/thai-input/style.css"; // ไม่บังคับ
import { ThaiIdInput, PhoneInput, MoneyInput } from "@inverz/thai-input";เลขบัตรประชาชน / เลขผู้เสียภาษี
const [id, setId] = useState("");
<ThaiIdInput value={id} onChange={(value, { valid, complete }) => setId(value)} />- แสดงเป็น
1-1017-00203-45-0ส่วนvalueที่ได้เป็นตัวเลขล้วน"1101700203450" - พิมพ์ครบ 13 หลักแล้วตรวจหลักสุดท้าย (checksum) ให้ ถ้าผิดจะบอกแค่ว่าเลขไม่ถูกต้อง ไม่บอกเลขที่ถูก เพื่อไม่ให้ใช้เดาเลขที่ผ่านการตรวจได้
ThaiTaxIdInputใช้กับเลขผู้เสียภาษีของนิติบุคคล (checksum แบบเดียวกัน) และค้นชื่อบริษัทได้ (ดูด้านล่าง)- ปิดข้อความใต้ช่องได้ด้วย
showStatus={false}
บัตรประชาชน / พาสปอร์ต และซ่อนเลข
<ThaiIdInput
label={{ id: "เลขบัตรประชาชน", passport: "เลขพาสปอร์ต" }}
required
allowPassport
maskable
value={value}
onChange={(value, { valid, documentType }) => setValue(value)}
/>allowPassportเพิ่มปุ่มสลับ "บัตรประชาชน / พาสปอร์ต" เลขพาสปอร์ตรับตัวอักษรอังกฤษกับตัวเลข 6–12 ตัว แปลงเป็นตัวพิมพ์ใหญ่ให้ (ไม่มี checksum จึงตรวจแค่รูปแบบ) สลับประเภทแล้วค่าจะถูกล้างmaskableเพิ่มปุ่มรูปตาสำหรับซ่อน/แสดงเลข (defaultMaskedให้เริ่มแบบซ่อน)label+requiredแสดงหัวช่องพร้อม*สีแดงlabelใส่เป็น{ id, passport }เพื่อให้เปลี่ยนตามประเภทได้documentTypeNameเพิ่ม hidden input ที่มีค่า"id"หรือ"passport"สำหรับส่งฟอร์ม
ค้นชื่อบริษัทจากเลขผู้เสียภาษี
<ThaiTaxIdInput
value={taxId}
onChange={setTaxId}
lookup
onLookup={(company, error) => setCompany(company)}
/>พอกรอกครบ checksum ผ่าน และเลขขึ้นต้นด้วย 0 (นิติบุคคล) จะค้นชื่อจาก API สาธารณะของกรมพัฒนาธุรกิจการค้า (DBD) แล้วแสดงใต้ช่อง เช่น "✓ บริษัท … จำกัด" ถ้าเลิกกิจการแล้วจะขึ้น "⚠ … · เลิก"
- เลขบุคคลธรรมดา (ไม่ขึ้นต้นด้วย 0) ไม่ถูกส่งไปค้นเลย ตรวจแค่ checksum
- ค้นไม่เจอ ถูกบล็อก หรือ API ของ DBD เปลี่ยน จะแสดงแค่ "เลขถูกต้อง" ตามผล checksum เหมือนไม่ได้เปิด lookup เช่น มูลนิธิ สมาคม หน่วยงานรัฐ ที่ไม่ได้จดกับ DBD
- ผลลัพธ์ถูกเก็บไว้ต่อหน้า เลขเดิมไม่ค้นซ้ำ และรอให้หยุดพิมพ์ก่อนค่อยค้น
- ถ้าอยากรู้ว่าค้นไม่เจอหรือค้นไม่ได้ ใช้
onLookup(company, error) - ระบบที่มีผู้ใช้มาก แนะนำให้ค้นผ่าน server ตัวเองแล้วเก็บ cache:
<ThaiTaxIdInput lookup={(taxId) => fetch(`/api/company/${taxId}`).then((r) => r.json())} />// server
import { lookupCompany } from "@inverz/thai-input/utils";
const company = await lookupCompany("0105500002383"); // null ถ้าไม่พบ
// { nameTh, nameEn, type, status, active, registeredDate, registeredCapital,
// address: { text, subdistrict, district, province, subdistrictId }, objectives }address.subdistrictId เป็นรหัสตำบลของกรมการปกครอง ใช้กับ @inverz/thai-address ได้ เช่น db.get(company.address.subdistrictId) จะได้รหัสไปรษณีย์ด้วย ก่อนใช้งานเชิงพาณิชย์ควรตรวจเงื่อนไขการใช้ข้อมูลของ DBD
เบอร์โทร
<PhoneInput value={tel} onChange={(value, { valid, type }) => setTel(value)} showStatus />- มือถือ
081-234-5678· กรุงเทพฯ02-123-4567· ต่างจังหวัด053-123-456· เบอร์สั้น Call Center1111· โทรฟรี1800-123-456 - วางเบอร์
+66 81 234 5678แล้วแปลงเป็น0812345678ให้เอง typeได้"mobile","landline","hotline","tollfree"หรือnullถ้าจะรับเฉพาะมือถือ ใส่mobileOnly
จำนวนเงิน
const [amount, setAmount] = useState(null);
<MoneyInput value={amount} onChange={setAmount} unit="บาท" showBahtText />- ใส่ comma ให้เองตอนพิมพ์ ออกจากช่องแล้วเติมทศนิยมให้ครบ (
1,250.50) valueเป็นnumberหรือnullตอนช่องว่างdecimals={0}สำหรับจำนวนเต็มallowNegativeถ้าต้องการค่าติดลบshowBahtTextแสดง "หนึ่งพันสองร้อยห้าสิบบาทห้าสิบสตางค์" ใต้ช่อง
ใช้ใน <form>
ใส่ name แล้วฟอร์มจะส่งค่าที่สะอาด (ไม่มีขีด ไม่มี comma) ผ่าน hidden input
<form onSubmit={handleSubmit}>
<ThaiIdInput name="national_id" required />
<PhoneInput name="phone" />
<MoneyInput name="salary" unit="บาท" />
</form>props อื่นของ <input> ส่งต่อได้หมด เช่น id, placeholder, disabled, required, onBlur, aria-* ส่วน className / style ใช้กับกล่องที่ครอบ
ตรวจฝั่ง server (ไม่ต้องมี React)
import { isThaiId, isThaiPhone, normalizeThaiPhone, bahtText } from "@inverz/thai-input/utils";
isThaiId("1-1017-00203-45-0"); // true
isThaiPhone("+66812345678"); // true
normalizeThaiPhone("+66 81 234 5678"); // "0812345678"
bahtText(1250.5); // "หนึ่งพันสองร้อยห้าสิบบาทห้าสิบสตางค์"ใช้กับ Zod:
const Customer = z.object({
nationalId: z.string().refine(isThaiId, "เลขบัตรประชาชนไม่ถูกต้อง"),
phone: z.string().refine(isThaiPhone, "เบอร์โทรไม่ถูกต้อง").transform(normalizeThaiPhone),
});ฟังก์ชันทั้งหมด (import จาก @inverz/thai-input ก็ได้):
| ฟังก์ชัน | ได้ |
|---|---|
| isThaiId(v) / isThaiTaxId(v) | ถูกต้องตาม checksum ไหม |
| thaiIdCheckDigit(first12) | หลักที่ 13 ที่ถูกต้อง |
| formatThaiId(v) | 1-1017-00203-45-0 |
| isThaiPhone(v) / thaiPhoneType(v) | ถูกต้องไหม / "mobile" "landline" "hotline" "tollfree" null |
| normalizeThaiPhone(v) | ตัวเลขล้วน ขึ้นต้นด้วย 0 |
| formatThaiPhone(v) | 081-234-5678 |
| toInternationalPhone(v) | +66812345678 |
| formatMoney(n, { decimals }) | 1,234.50 |
| bahtText(n) | คำอ่านจำนวนเงิน |
| lookupCompany(taxId) | ข้อมูลนิติบุคคลจาก DBD (async) |
| digitsOnly(v) | ตัวเลขล้วน |
ปรับธีม
ตัวแปร --tin-* (เช่น --tin-brand, --tin-danger) ถ้าไม่ได้ตั้งจะใช้ค่าจาก --tdp-* ของ @inverz/thai-datepicker ดูทั้งหมดที่ src/style.css หรือไม่ import CSS แล้วแต่ง .tin-input เองก็ได้
License
MIT © 2026 Inverz Solutions Co.,Ltd.
