th-auto-address
v1.0.1
Published
Thai address autocomplete React components using shadcn/ui Combobox
Maintainers
Readme
th-auto-address
React shared components สำหรับกรอกที่อยู่ไทยแบบ autocomplete ด้วย shadcn/ui Combobox
รองรับ: จังหวัด, อำเภอ/เขต, ตำบล/แขวง, รหัสไปรษณีย์ พร้อม cascading filter อัตโนมัติ
Features
- Combobox พร้อมค้นหา สำหรับทุกระดับที่อยู่
- Cascading filter: เลือกจังหวัด → กรองอำเภอ → กรองตำบล → auto-fill รหัสไปรษณีย์
- รองรับ 2 ภาษา (
language="th"/language="en") - Customizable labels
- ใช้งานร่วมกับ
react-hook-form+zodและ TanStack Form - Type-safe 100% (ไม่มี
any) - รองรับ shadcn/ui theme โดยอ้างอิง CSS variables จากโปรเจคปลายทาง
- ข้อมูลครบ: 76 จังหวัด, 918 อำเภอ, 7,387 ตำบล
Installation
npm install th-auto-addressPeer dependencies:
npm install react react-domQuick Start
แบบง่าย — component เดียวจบ
import { ThaiAddressForm } from "th-auto-address";
function MyPage() {
return (
<ThaiAddressForm
onChange={(address) => {
console.log(address);
// { province: "กรุงเทพมหานคร", provinceCode: 10,
// amphoe: "พระนคร", amphoeCode: 1001,
// district: "พระบรมมหาราชวัง", zipcode: 10200 }
}}
/>
);
}English
<ThaiAddressForm language="en" onChange={handleChange} />Custom Labels
<ThaiAddressForm
language="en"
labels={{
province: "Province / จังหวัด",
amphoe: "District / อำเภอ",
district: "Sub-district / ตำบล",
zipcode: "ZIP Code / รหัสไปรษณีย์",
}}
onChange={handleChange}
/>แยก Components (ใช้ Hook)
import {
useThaiAddress,
ProvinceCombobox,
AmphoeCombobox,
DistrictCombobox,
ZipcodeCombobox,
} from "th-auto-address";
function AddressForm() {
const ctx = useThaiAddress({
language: "th",
onChange: (address) => console.log(address),
});
return (
<>
<ProvinceCombobox
options={ctx.provinceOptions}
value={ctx.provinceCode ? String(ctx.provinceCode) : ""}
onValueChange={ctx.setProvince}
/>
<AmphoeCombobox
options={ctx.amphoeOptions}
value={ctx.amphoeCode ? String(ctx.amphoeCode) : ""}
onValueChange={ctx.setAmphoe}
disabled={!ctx.provinceCode}
/>
<DistrictCombobox
options={ctx.districtOptions}
value={ctx.district}
onValueChange={ctx.setDistrict}
disabled={!ctx.amphoeCode}
/>
<ZipcodeCombobox
options={ctx.zipcodeOptions}
value={ctx.zipcode ? String(ctx.zipcode) : ""}
onValueChange={ctx.setZipcode}
disabled={!ctx.district}
/>
</>
);
}Render Props — Custom Layout
<ThaiAddressForm onChange={handleChange}>
{(ctx) => (
<div className="flex flex-col gap-4">
<ProvinceCombobox
options={ctx.provinceOptions}
value={ctx.provinceCode ? String(ctx.provinceCode) : ""}
onValueChange={ctx.setProvince}
/>
{/* ... custom layout ... */}
<button onClick={ctx.reset}>Reset</button>
</div>
)}
</ThaiAddressForm>Form Library Integration
react-hook-form + zod
import { z } from "zod";
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import {
createThaiAddressSchema,
useThaiAddress,
ProvinceCombobox,
} from "th-auto-address";
const addressSchema = createThaiAddressSchema(z);
const formSchema = z.object({
name: z.string().min(1),
address: addressSchema,
});
function MyForm() {
const form = useForm({
resolver: zodResolver(formSchema),
});
const addr = useThaiAddress({
onChange: (address) => {
if (address) form.setValue("address", address, { shouldValidate: true });
},
});
return (
<Controller
control={form.control}
name="address.province"
render={({ field }) => (
<ProvinceCombobox
ref={field.ref}
name={field.name}
onBlur={field.onBlur}
options={addr.provinceOptions}
value={addr.provinceCode ? String(addr.provinceCode) : ""}
onValueChange={addr.setProvince}
/>
)}
/>
);
}Plain Validation (ไม่ต้องใช้ zod)
import { validateThaiAddress } from "th-auto-address";
const errors = validateThaiAddress(address);
// [{ field: "province", message: "กรุณาเลือกจังหวัด" }, ...]Tailwind CSS Setup
โปรเจคที่ใช้ shadcn/ui อยู่แล้ว
เพิ่ม content path ใน tailwind.config.ts:
export default {
content: [
"./src/**/*.{ts,tsx}",
"./node_modules/th-auto-address/src/**/*.{ts,tsx}",
],
};Components จะใช้ CSS variables จาก shadcn theme (--background, --border, --input, etc.) โดยอัตโนมัติ
โปรเจคที่ไม่ได้ใช้ shadcn
import "th-auto-address/styles.css";API Reference
Components
| Component | Props | Description |
|---|---|---|
| ThaiAddressForm | language?, labels?, onChange?, defaultValue?, children? | All-in-one form |
| ProvinceCombobox | options, value, onValueChange, language? | Province selector |
| AmphoeCombobox | options, value, onValueChange, language? | District selector |
| DistrictCombobox | options, value, onValueChange, language? | Sub-district selector |
| ZipcodeCombobox | options, value, onValueChange, language? | Postal code selector |
ทุก Combobox รองรับ ref, name, onBlur, disabled, className
Hook
const ctx = useThaiAddress({
language: "th", // "th" | "en"
defaultValue: { ... }, // Partial<ThaiAddress>
onChange: (address) => {},
});Types
interface ThaiAddress {
province: string;
provinceCode: number;
amphoe: string;
amphoeCode: number;
district: string;
zipcode: number;
}
type Language = "th" | "en";Data
| Level | Count | English | |---|---|---| | Province (จังหวัด) | 76 | RTGS romanized names | | Amphoe (อำเภอ/เขต) | 918 | Thai (proper nouns) | | District (ตำบล/แขวง) | 7,387 | Thai (proper nouns) |
Source: Thai Post via jquery.Thailand.js
Example
cd example
npm install
npm run devเปิด http://localhost:5173 เพื่อดูตัวอย่าง 5 แบบ: Basic, English, Custom Labels, Render Props, React Hook Form + Zod
Credits
โปรเจคนี้ต่อยอดจาก jquery.Thailand.js โดย @earthchie
- ฐานข้อมูลที่อยู่ไทยทั้งหมดมาจาก
raw_database.jsonของ jquery.Thailand.js - แนวคิดเดิม: ระบบ Auto Complete ที่อยู่ไทย อย่างที่มันควรเป็น
- Original license: WTFPL
ขอบคุณ @earthchie และ contributors ทุกคนที่ดูแลฐานข้อมูลที่อยู่ไทย
License
MIT
