UNPKG

react-data-entry

Version:
512 lines (424 loc) 13.6 kB
# React Data Entry [![npm version](https://img.shields.io/npm/v/react-data-entry.svg)](https://www.npmjs.com/package/react-data-entry) [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC) Thư viện React components chuyên dụng cho việc nhập liệu dữ liệu (data entry), được tích hợp sẵn với **React Hook Form** và **Ant Design**, cung cấp các component tối ưu cho form validation và UI/UX hiện đại. ## ✨ Tính năng - 🎯 **16+ Components** nhập liệu đa dạng và chuyên biệt - 🔗 **Tích hợp React Hook Form** sẵn có với validation - 🎨 **Ant Design UI** đẹp mắt và nhất quán - 📱 **Responsive** hỗ trợ mọi kích thước màn hình - ⚡ **Performance** tối ưu với React.memo và useCallback - 🛡️ **TypeScript** hỗ trợ đầy đủ với type safety - 🎛️ **Flexible** cấu hình linh hoạt cho mọi use case - 🔧 **Error Handling** xử lý lỗi tự động và fallback UI ## 📦 Cài đặt ```bash npm install react-data-entry ``` ```bash yarn add react-data-entry ``` ```bash pnpm add react-data-entry ``` ### Peer Dependencies Thư viện yêu cầu các dependencies sau: ```bash npm install react react-dom react-hook-form ``` ## 🚀 Sử dụng cơ bản ### Cách 1: Sử dụng RenderDataEntry (Khuyên dùng) Component chính `RenderDataEntry` cung cấp cách sử dụng thống nhất cho tất cả các loại input: ```tsx import React from "react"; import { useForm } from "react-hook-form"; import { RenderDataEntry, KeyEditType } from "react-data-entry"; const MyForm = () => { const hookForm = useForm(); const fieldConfig: KeyEditType = { type: "text", key: "username", label: "Tên đăng nhập", placeholder: "Nhập tên đăng nhập", rules: { required: "Vui lòng nhập tên đăng nhập" }, width: "300px", }; return ( <form onSubmit={hookForm.handleSubmit(console.log)}> <RenderDataEntry data={fieldConfig} hookForm={hookForm} size="large" /> <button type="submit">Gửi</button> </form> ); }; ``` ### Cách 2: Sử dụng từng Component riêng lẻ ```tsx import React from "react"; import { useForm, Controller } from "react-hook-form"; import { CTextfield, CCalendar, CSelector } from "react-data-entry"; const MyForm = () => { const { control, handleSubmit } = useForm(); return ( <form onSubmit={handleSubmit(console.log)}> <Controller name="username" control={control} rules={{ required: "Vui lòng nhập tên" }} render={({ field, fieldState: { error } }) => ( <CTextfield data={{ label: "Tên đăng nhập", placeholder: "Nhập tên đăng nhập", required: true, message: error?.message, }} field={field} size="large" /> )} /> </form> ); }; ``` ## 📋 Danh sách Components | Component | Type | Mô tả | | ---------------- | ------------ | ------------------------------------ | | `CTextfield` | `text` | Input text cơ bản | | `CInputNumber` | `number` | Input số với validation | | `CTextarea` | `textarea` | Textarea nhiều dòng | | `CPassword` | `password` | Input mật khẩu với toggle visibility | | `CSwitch` | `switch` | Switch on/off | | `CCalendar` | `date` | Date picker | | `CRangeCalendar` | `range-date` | Date range picker | | `CTime` | `time` | Time picker | | `CSelector` | `select` | Dropdown select (single/multiple) | | `CCurrency` | `currency` | Input tiền tệ với format | | `CEditor` | `editor` | Rich text editor (Quill) | | `CUpload` | `upload` | File upload với preview | | `CRadio` | `radio` | Radio button group | | `CLink` | `link` | Link input với validation URL | | `CColorPicker` | `color` | Color picker | ## 🔧 Cấu hình Field Data ### Interface KeyEditType ```typescript interface KeyEditType { type: RenderDataEntryType; // Loại component key: string; // Field name label: string; // Nhãn hiển thị role?: any[] | null; // Phân quyền (nếu có) width?: string; // Chiều rộng placeholder?: string; // Placeholder text direction?: "row" | "column"; // Hướng layout labelWidth?: string; // Chiều rộng label rules?: any; // Validation rules disabled?: boolean; // Vô hiệu hóa defaultValue?: any; // Giá trị mặc định // Cho số và currency max?: number; min?: number; suffix?: string; // Cho date min_date?: string; max_date?: string; picker?: "week" | "month" | "year" | "quarter"; formatCalendar?: string; // Cho select type_select?: "multiple" | "single"; options?: any[]; // Cho textfield type_text?: "text" | "number"; // Cho upload uploadImage?: any; length_img?: number; } ``` ## 📝 Ví dụ chi tiết ### 1. Text Input với Validation ```tsx const textConfig: KeyEditType = { type: "text", key: "fullName", label: "Họ và tên", placeholder: "Nhập họ và tên đầy đủ", rules: { required: "Vui lòng nhập họ và tên", minLength: { value: 2, message: "Tên phải có ít nhất 2 ký tự", }, }, width: "100%", direction: "column", }; ``` ### 2. Number Input với Min/Max ```tsx const numberConfig: KeyEditType = { type: "number", key: "age", label: "Tuổi", placeholder: "Nhập tuổi", min: 18, max: 100, rules: { required: "Vui lòng nhập tuổi", min: { value: 18, message: "Tuổi phải từ 18 trở lên" }, }, }; ``` ### 3. Date Picker với Range ```tsx const dateConfig: KeyEditType = { type: "date", key: "birthDate", label: "Ngày sinh", picker: "date", formatCalendar: "DD/MM/YYYY", min_date: "1900-01-01", max_date: new Date().toISOString().split("T")[0], rules: { required: "Vui lòng chọn ngày sinh" }, }; ``` ### 4. Select với Options ```tsx const selectConfig: KeyEditType = { type: "select", key: "skills", label: "Kỹ năng", type_select: "multiple", options: [ { label: "React", value: "react" }, { label: "Vue", value: "vue" }, { label: "Angular", value: "angular" }, { label: "Node.js", value: "nodejs" }, ], placeholder: "Chọn kỹ năng của bạn", }; ``` ### 5. Currency Input ```tsx const currencyConfig: KeyEditType = { type: "currency", key: "salary", label: "Mức lương mong muốn", suffix: "VNĐ", min: 0, max: 100000000, placeholder: "Nhập mức lương", }; ``` ### 6. Rich Text Editor ```tsx const editorConfig: KeyEditType = { type: "editor", key: "description", label: "Mô tả chi tiết", placeholder: "Nhập mô tả...", rules: { required: "Vui lòng nhập mô tả", validate: (value: string) => { const textLength = value.replace(/<[^>]*>/g, "").length; if (textLength < 10) return "Mô tả phải có ít nhất 10 ký tự"; return true; }, }, }; ``` ### 7. File Upload ```tsx const uploadConfig: KeyEditType = { type: "upload", key: "avatar", label: "Ảnh đại diện", length_img: 1, uploadImage: { accept: "image/*", maxSize: 5 * 1024 * 1024, // 5MB listType: "picture-card", }, }; ``` ## 🎨 Styling và Customization ### Custom CSS Classes ```css /* Custom styles */ .custom-form-field { margin-bottom: 16px; } .custom-form-field .ant-form-item-label { font-weight: 600; } .custom-form-field .ant-input { border-radius: 8px; } ``` ### Sử dụng className ```tsx const fieldConfig: KeyEditType = { type: "text", key: "username", label: "Username", // className sẽ được áp dụng cho field container }; ``` ## 🌟 Form hoàn chỉnh ```tsx import React from "react"; import { useForm } from "react-hook-form"; import { RenderDataEntry, KeyEditType } from "react-data-entry"; const UserRegistrationForm = () => { const hookForm = useForm(); const formFields: KeyEditType[] = [ { type: "text", key: "username", label: "Tên đăng nhập", placeholder: "Nhập tên đăng nhập", rules: { required: "Vui lòng nhập tên đăng nhập" }, }, { type: "password", key: "password", label: "Mật khẩu", placeholder: "Nhập mật khẩu", rules: { required: "Vui lòng nhập mật khẩu", minLength: { value: 6, message: "Mật khẩu ít nhất 6 ký tự" }, }, }, { type: "text", key: "email", label: "Email", placeholder: "Nhập email", rules: { required: "Vui lòng nhập email", pattern: { value: /^\S+@\S+$/i, message: "Email không hợp lệ", }, }, }, { type: "date", key: "birthDate", label: "Ngày sinh", picker: "date", rules: { required: "Vui lòng chọn ngày sinh" }, }, { type: "select", key: "gender", label: "Giới tính", type_select: "single", options: [ { label: "Nam", value: "male" }, { label: "Nữ", value: "female" }, { label: "Khác", value: "other" }, ], }, ]; const onSubmit = (data: any) => { console.log("Form Data:", data); }; return ( <form onSubmit={hookForm.handleSubmit(onSubmit)}> <div style={{ display: "grid", gap: "16px", maxWidth: "600px" }}> {formFields.map((field) => ( <RenderDataEntry key={field.key} data={field} hookForm={hookForm} size="large" /> ))} </div> <div style={{ marginTop: "24px" }}> <button type="submit" style={{ padding: "12px 24px", backgroundColor: "#1890ff", color: "white", border: "none", borderRadius: "6px", cursor: "pointer", }} > Đăng ký </button> </div> </form> ); }; export default UserRegistrationForm; ``` ## 🔧 Props Reference ### RenderDataEntry Props | Prop | Type | Default | Mô tả | | ---------------- | -------------------------------- | --------- | ------------------------ | | `data` | `KeyEditType` | - | Cấu hình field | | `hookForm` | `object` | - | React Hook Form instance | | `disabled` | `boolean` | `false` | Vô hiệu hóa field | | `size` | `'large' \| 'middle' \| 'small'` | `'large'` | Kích thước component | | `customOnChange` | `function` | - | Custom onChange handler | ### Common Field Props | Prop | Type | Default | Mô tả | | ------------- | ------------------- | ---------- | ------------------ | | `label` | `string` | - | Nhãn field | | `placeholder` | `string` | - | Placeholder text | | `width` | `string` | `'100%'` | Chiều rộng | | `direction` | `'row' \| 'column'` | `'column'` | Layout direction | | `labelWidth` | `string` | - | Chiều rộng label | | `disabled` | `boolean` | `false` | Trạng thái disable | | `required` | `boolean` | `false` | Bắt buộc nhập | ## 🚨 Error Handling Thư viện có hệ thống xử lý lỗi tự động: ```tsx // Error Boundary tự động bắt lỗi render <ErrorBoundary fallback={<div>Có lỗi xảy ra</div>}> <RenderDataEntry data={fieldConfig} hookForm={hookForm} /> </ErrorBoundary>; // Validation errors từ React Hook Form const rules = { required: "Trường này bắt buộc", validate: (value) => { if (!value) return "Giá trị không hợp lệ"; return true; }, }; ``` ## 🏗️ Development ### Build từ source ```bash # Clone repository git clone https://github.com/HiNT89/react-data-entry.git cd react-data-entry # Install dependencies npm install # Build npm run build # Pack for testing npm run pack:local ``` ### Project Structure ``` src/ ├── components/ # Shared components ├── types/ # TypeScript definitions ├── utils/ # Utility functions ├── *.tsx # Main components ├── styles.css # Global styles └── index.tsx # Main exports ``` ## 📄 License ISC License - xem file [LICENSE](LICENSE) để biết thêm chi tiết. ## 🤝 Contributing Contributions are welcome! Vui lòng đọc [CONTRIBUTING.md](CONTRIBUTING.md) để biết hướng dẫn chi tiết. ## 📞 Support - 🐛 **Issues**: [GitHub Issues](https://github.com/HiNT89/react-data-entry/issues) - 💬 **Discussions**: [GitHub Discussions](https://github.com/HiNT89/react-data-entry/discussions) - 📧 **Email**: support@hint89.dev --- Được phát triển bởi **HiNT** với ❤️