{"_id":"@benyue1978/next-dynamic-forms","_rev":"4-6a48fa9b946c75ca0acc3b0d30b626bd","name":"@benyue1978/next-dynamic-forms","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@benyue1978/next-dynamic-forms","version":"0.1.0","keywords":["react","forms","dynamic","configuration","typescript","i18n","nextjs"],"author":{"name":"benyue1978"},"license":"MIT","_id":"@benyue1978/next-dynamic-forms@0.1.0","maintainers":[{"name":"benyue","email":"yuesong@gmail.com"}],"dist":{"shasum":"de27ed1d50977ac15b6e67e987e5bb7995dc7a2f","tarball":"https://registry.npmjs.org/@benyue1978/next-dynamic-forms/-/next-dynamic-forms-0.1.0.tgz","fileCount":6,"integrity":"sha512-kndTXf+dD63SV3DnC3Z+nq4S+y3+w57c70DdojJ912kOm8A9PId4WF4eavvnsHhFGOHkyNJkBMkFkcMUk4XvOQ==","signatures":[{"sig":"MEYCIQCviOTJDe93+vKrkDs7yREnayr5+9XVoIf4W3M8XvkaXAIhANhCRVQj/D4Fpgg/4BGkwyRm5e/4l28lnF6akSlBlBHY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42997},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","import":"./dist/types/index.mjs","require":"./dist/types/index.js"}},"gitHead":"fb2f2157a85965b1cdee52869badbb97d34c4511","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest","build":"tsup src/index.ts --format cjs,esm --dts","clean":"rm -rf dist","test:run":"vitest run","test:unit":"vitest","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"benyue","email":"yuesong@gmail.com"},"_npmVersion":"11.4.2","description":"Configuration-driven dynamic forms with built-in i18n support","directories":{},"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","jsdom":"^26.1.0","eslint":"^8.57.0","vitest":"^3.2.4","typescript":"^5.0.0","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","eslint-plugin-react":"^7.34.1","@testing-library/react":"^16.3.0","eslint-config-prettier":"^9.1.0","@testing-library/jest-dom":"^6.6.3","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"next":">=14.0.0","react":">=18.0.0","next-intl":">=3.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/next-dynamic-forms_0.1.0_1753489540591_0.5390069959475132","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@benyue1978/next-dynamic-forms","version":"0.1.1","keywords":["react","forms","dynamic","configuration","typescript","i18n","nextjs"],"author":{"name":"benyue1978"},"license":"MIT","_id":"@benyue1978/next-dynamic-forms@0.1.1","maintainers":[{"name":"benyue","email":"yuesong@gmail.com"}],"dist":{"shasum":"53d002fe7b93cd1c3efe69a83d2dd351aaa9a2ef","tarball":"https://registry.npmjs.org/@benyue1978/next-dynamic-forms/-/next-dynamic-forms-0.1.1.tgz","fileCount":11,"integrity":"sha512-9uox+SYcGKOQJgWh2G2ErjkfjEqYBACVNysqalRS/6q/mgNbDFvIi32/uytDZgjMXk5sB0DJtzKlUybiWeBAaw==","signatures":[{"sig":"MEQCIGyCOAdJetX6yFht+zLGii8uhMCujbkfecmZygPbGFyVAiBV2PT0KBZR2QYzWjDSN8W3NRQcbOx9k37lHXKaGT7LJQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55467},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.mjs","require":"./dist/core.js"}},"gitHead":"9edfd59eaecd7312f19ca052d03aeb3cc7fc045e","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest","build":"tsup","clean":"rm -rf dist","test:run":"vitest run","test:unit":"vitest","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"benyue","email":"yuesong@gmail.com"},"_npmVersion":"11.4.2","description":"Configuration-driven dynamic forms with built-in i18n support","directories":{},"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","jsdom":"^26.1.0","eslint":"^8.57.0","vitest":"^3.2.4","typescript":"^5.0.0","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","eslint-plugin-react":"^7.34.1","@testing-library/react":"^16.3.0","eslint-config-prettier":"^9.1.0","@testing-library/jest-dom":"^6.6.3","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"next":">=14.0.0","react":">=18.0.0","next-intl":">=3.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/next-dynamic-forms_0.1.1_1753507256838_0.1851289932897735","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@benyue1978/next-dynamic-forms","version":"0.1.2","keywords":["react","forms","dynamic","configuration","typescript","i18n","nextjs"],"author":{"name":"benyue1978"},"license":"MIT","_id":"@benyue1978/next-dynamic-forms@0.1.2","maintainers":[{"name":"benyue","email":"yuesong@gmail.com"}],"dist":{"shasum":"48790d4bc007e3e492015a2381f68d1837dacf69","tarball":"https://registry.npmjs.org/@benyue1978/next-dynamic-forms/-/next-dynamic-forms-0.1.2.tgz","fileCount":13,"integrity":"sha512-aA9wiJLqXvkEqfQMpVYi2776V9hDeAOBBGHP8oZz1g6W3wRD2RCiTImBqfnF0mj4qbyjn6Ej8ZKHnle1JLQtYg==","signatures":[{"sig":"MEUCIQCCuR+1vVEGEUI+yIznjU59E0zIGThDcu2xuwcZKCNHrQIgXSuoxvNPuiDNQU9OcoRJjw28pFwwVq/+Z15R2k4pdR4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67549},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.mjs","require":"./dist/core.js"}},"gitHead":"0f34da6a7f6ff2ad1f123cb1de470e74dc1b5610","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsup","clean":"rm -rf dist","test:run":"vitest run","test:unit":"vitest run","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"benyue","email":"yuesong@gmail.com"},"_npmVersion":"11.4.2","description":"Configuration-driven dynamic forms with built-in i18n support","directories":{},"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","jsdom":"^26.1.0","eslint":"^8.57.0","vitest":"^3.2.4","typescript":"^5.0.0","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","eslint-plugin-react":"^7.34.1","@testing-library/react":"^16.3.0","eslint-config-prettier":"^9.1.0","@testing-library/jest-dom":"^6.6.3","@testing-library/user-event":"^14.6.1"},"peerDependencies":{"next":">=14.0.0","react":">=18.0.0","next-intl":">=3.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/next-dynamic-forms_0.1.2_1753584252959_0.2744566499711407","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@benyue1978/next-dynamic-forms","version":"0.1.3","description":"Configuration-driven dynamic forms with built-in i18n support","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.mjs","require":"./dist/core.js"}},"publishConfig":{"access":"public"},"keywords":["react","forms","dynamic","configuration","typescript","i18n","nextjs"],"author":{"name":"benyue1978"},"license":"MIT","peerDependencies":{"next":">=14.0.0","next-intl":">=3.0.0","react":">=18.0.0","react-dom":">=18.0.0"},"devDependencies":{"@testing-library/jest-dom":"^6.6.3","@testing-library/react":"^16.3.0","@testing-library/user-event":"^14.6.1","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","eslint":"^8.57.0","eslint-config-prettier":"^9.1.0","eslint-plugin-react":"^7.34.1","jsdom":"^26.1.0","tsup":"^8.5.0","typescript":"^5.0.0","vitest":"^3.2.4"},"scripts":{"build":"tsup","dev":"tsup --watch","clean":"rm -rf dist","test":"vitest run","test:unit":"vitest run","test:run":"vitest run","test:coverage":"vitest run --coverage","lint":"eslint src test","typecheck":"tsc --noEmit"},"_id":"@benyue1978/next-dynamic-forms@0.1.3","_integrity":"sha512-TMNF2g/gLrp7kDoJ4ShGRHDkYAMHv2hRkPIKyI8LlRYKYGje6Cqy2jDEKXiuqoB/awQnDp4GpdcNriH12FZgbQ==","_resolved":"/private/var/folders/qn/mmxj18_d3sb19_jmmlf055hh0000gn/T/4ed26cf498c7ae83388faae9c96ad5b9/benyue1978-next-dynamic-forms-0.1.3.tgz","_from":"file:benyue1978-next-dynamic-forms-0.1.3.tgz","_nodeVersion":"24.3.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-TMNF2g/gLrp7kDoJ4ShGRHDkYAMHv2hRkPIKyI8LlRYKYGje6Cqy2jDEKXiuqoB/awQnDp4GpdcNriH12FZgbQ==","shasum":"454e7d0f8fafef3a37e5e9092cf46eee10ef7b80","tarball":"https://registry.npmjs.org/@benyue1978/next-dynamic-forms/-/next-dynamic-forms-0.1.3.tgz","fileCount":13,"unpackedSize":78668,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA3I40ocjXG8oskd4V77/1sIoqys+rzCax5ExaFVBZMpAiEApUIG6uBw3EPvZHRjXuVBGX+ItFfW4rUqcWyMXP9Qs2I="}]},"_npmUser":{"name":"benyue","email":"yuesong@gmail.com"},"directories":{},"maintainers":[{"name":"benyue","email":"yuesong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/next-dynamic-forms_0.1.3_1753587607706_0.7430598125638563"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-26T00:25:40.441Z","modified":"2025-07-27T03:40:08.064Z","0.1.0":"2025-07-26T00:25:40.776Z","0.1.1":"2025-07-26T05:20:57.023Z","0.1.2":"2025-07-27T02:44:13.136Z","0.1.3":"2025-07-27T03:40:07.879Z"},"author":{"name":"benyue1978"},"license":"MIT","keywords":["react","forms","dynamic","configuration","typescript","i18n","nextjs"],"description":"Configuration-driven dynamic forms with built-in i18n support","maintainers":[{"name":"benyue","email":"yuesong@gmail.com"}],"readme":"# @benyue1978/next-dynamic-forms\n\nA configuration-driven dynamic form system with multi-step forms, built-in internationalization, and UI component adaptation.\n\n## 🚀 Quick Start\n\n### Installation\n\n```bash\nnpm install @benyue1978/next-dynamic-forms\n# or\npnpm add @benyue1978/next-dynamic-forms\n# or\nyarn add @benyue1978/next-dynamic-forms\n```\n\n### Basic Usage\n\n```tsx\nimport { DynamicForm } from '@benyue1978/next-dynamic-forms/core'\n\n// 1. Define UI components\nconst uiComponents = {\n  Input: MyInput,\n  Textarea: MyTextarea,\n  Label: MyLabel,\n  Button: MyButton,\n  ProgressStep: MyProgressStep\n}\n\n// 2. Define i18n adapter\nconst i18nAdapter = {\n  t: (key: string, params?: Record<string, any>) => {\n    // Your translation logic\n    return translate(key, params)\n  }\n}\n\n// 3. Use the component\nfunction MyForm() {\n  const [formData, setFormData] = useState({})\n  const [currentStep, setCurrentStep] = useState(0)\n  \n  return (\n    <DynamicForm\n      config={formConfig}\n      currentStepIndex={currentStep}\n      formData={formData}\n      onDataChange={(newData) => setFormData(prev => ({ ...prev, ...newData }))}\n      onNext={() => setCurrentStep(prev => prev + 1)}\n      onPrevious={() => setCurrentStep(prev => prev - 1)}\n      isFirstStep={currentStep === 0}\n      isLastStep={currentStep === formConfig.steps.length - 1}\n      uiComponents={uiComponents}\n      i18n={i18nAdapter}\n    />\n  )\n}\n```\n\n### Customizing Form Texts\n\nYou can customize all form texts without relying on specific translation keys:\n\n```tsx\n<DynamicForm\n  config={formConfig}\n  // ... other props\n  buttonTexts={{\n    previous: '上一步',\n    next: '下一步',\n    submit: '提交',\n    back: '返回'\n  }}\n  labels={{\n    optional: '(可选)',\n    pleaseSelect: '请选择...'\n  }}\n  errorMessages={{\n    requiredFieldsMissing: '请填写必填字段: {fields}'\n  }}\n/>\n```\n\n### Customizing Form Styling\n\nThe form now provides comprehensive styling customization with sensible defaults:\n\n```tsx\n<DynamicForm\n  config={formConfig}\n  // ... other props\n  // Container styling\n  className=\"my-custom-form\"\n  containerClassName=\"max-w-2xl mx-auto\"\n  headerClassName=\"text-center mb-8\"\n  formClassName=\"space-y-6\"\n  buttonContainerClassName=\"flex justify-between pt-6\"\n  \n  // Field styling\n  fieldClassName=\"mb-4\"\n  fieldContainerClassName=\"bg-gray-50 p-4 rounded-lg\"\n  fieldLabelClassName=\"text-lg font-semibold\"\n  fieldInputClassName=\"border-2 border-blue-300 focus:border-blue-500\"\n  fieldIconClassName=\"text-blue-500\"\n  fieldRequiredClassName=\"text-red-600\"\n  fieldOptionalClassName=\"text-gray-400 italic\"\n/>\n```\n\n### Default Styling\n\nThe form uses Tailwind CSS classes by default, providing a clean, modern appearance:\n\n```typescript\n// Default field styles\n{\n  label: 'flex items-center gap-2 text-sm font-medium text-gray-700 mb-2',\n  input: 'w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent',\n  icon: 'absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 pointer-events-none',\n  required: 'text-red-500 font-bold',\n  optional: 'text-gray-500 text-sm font-normal'\n}\n```\n\n## 🎯 Next.js + next-intl Integration\n\n### Option 1: Simple Adapter (Recommended)\n\nCreate an adapter file `lib/dynamic-forms-adapter.tsx`:\n\n```tsx\n'use client'\n\nimport React from 'react'\nimport { useTranslations } from 'next-intl'\nimport { DynamicForm, UIComponents, I18nAdapter } from '@benyue1978/next-dynamic-forms/core'\n// Import your UI components\nimport { Input, Textarea, Label, Button } from '@/components/ui'\n\n// Define UI component mapping\nexport const uiComponents: UIComponents = {\n  Input, Textarea, Label, Button\n}\n\n// Create Next.js adapter component\nexport function NextJSDynamicForm(props: {\n  config: any\n  currentStepIndex: number\n  formData: any\n  onDataChange: (data: any) => void\n  onNext: () => void\n  onPrevious: () => void\n  isFirstStep: boolean\n  isLastStep: boolean\n  // Optional text customization\n  buttonTexts?: {\n    previous?: string;\n    next?: string;\n    submit?: string;\n    back?: string;\n  };\n  labels?: {\n    optional?: string;\n    pleaseSelect?: string;\n  };\n  errorMessages?: {\n    requiredFieldsMissing?: string;\n  };\n}) {\n  const t = useTranslations()\n  \n  const i18nAdapter: I18nAdapter = {\n    t: (key: string, params?: Record<string, any>) => t(key, params)\n  }\n\n  return (\n    <DynamicForm\n      {...props}\n      uiComponents={uiComponents}\n      i18n={i18nAdapter}\n    />\n  )\n}\n```\n\nUsage:\n\n```tsx\nimport { NextJSDynamicForm } from '@/lib/dynamic-forms-adapter'\n\nfunction MyPage() {\n  const [formData, setFormData] = useState({})\n  const [currentStep, setCurrentStep] = useState(0)\n  \n  return (\n    <NextJSDynamicForm\n      config={formConfig}\n      currentStepIndex={currentStep}\n      formData={formData}\n      onDataChange={(newData) => setFormData(prev => ({ ...prev, ...newData }))}\n      onNext={() => setCurrentStep(prev => prev + 1)}\n      onPrevious={() => setCurrentStep(prev => prev - 1)}\n      isFirstStep={currentStep === 0}\n      isLastStep={currentStep === formConfig.steps.length - 1}\n      buttonTexts={{\n        submit: 'Generate Project',\n        back: 'Back to Projects'\n      }}\n    />\n  )\n}\n```\n\n### Option 2: Built-in Adapter\n\n```tsx\nimport { createNextJSAdapter } from '@benyue1978/next-dynamic-forms'\n\nconst NextJSForm = createNextJSAdapter(uiComponents)\n\nfunction MyPage() {\n  const [formData, setFormData] = useState({})\n  const [currentStep, setCurrentStep] = useState(0)\n  \n  return (\n    <NextJSForm \n      config={formConfig}\n      currentStepIndex={currentStep}\n      formData={formData}\n      onDataChange={(newData) => setFormData(prev => ({ ...prev, ...newData }))}\n      onNext={() => setCurrentStep(prev => prev + 1)}\n      onPrevious={() => setCurrentStep(prev => prev - 1)}\n      isFirstStep={currentStep === 0}\n      isLastStep={currentStep === formConfig.steps.length - 1}\n      buttonTexts={{\n        submit: 'Generate Project',\n        back: 'Back to Projects'\n      }}\n    />\n  )\n}\n```\n\n## 🔧 Other Framework Adapters\n\n### React + react-i18next\n\n```tsx\nimport { useTranslation } from 'react-i18next'\nimport { DynamicForm } from '@benyue1978/next-dynamic-forms/core'\n\nfunction ReactI18nForm(props) {\n  const { t } = useTranslation()\n  \n  const i18nAdapter = {\n    t: (key: string, params?: Record<string, any>) => t(key, params)\n  }\n\n  return <DynamicForm {...props} i18n={i18nAdapter} />\n}\n```\n\n### No Internationalization\n\n```tsx\nimport { createBasicAdapter } from '@benyue1978/next-dynamic-forms'\n\nconst BasicForm = createBasicAdapter(uiComponents)\n// Will use keys as display text\n```\n\n## 📝 Configuration File Format\n\n```json\n{\n  \"id\": \"new-project\",\n  \"templateName\": \"new_project_template\",\n  \"steps\": [\n    {\n      \"id\": \"step1\",\n      \"title\": \"Basic Information\",\n      \"description\": \"Please fill in the basic project information\",\n      \"fields\": [\n        {\n          \"name\": \"projectName\",\n          \"type\": \"input\",\n          \"label\": \"Project Name\",\n          \"placeholder\": \"Enter project name\",\n          \"required\": true\n        },\n        {\n          \"name\": \"description\",\n          \"type\": \"textarea\",\n          \"label\": \"Description\",\n          \"placeholder\": \"Enter project description\",\n          \"rows\": 4\n        }\n      ]\n    }\n  ]\n}\n```\n\n## 🎨 UI Component Requirements\n\nYour UI components need to satisfy the following interface:\n\n```tsx\ninterface UIComponents {\n  Input: React.ComponentType<{\n    id?: string\n    value: string\n    onChange: (value: string) => void\n    placeholder?: string\n    required?: boolean\n    className?: string\n  }>\n  \n  Textarea: React.ComponentType<{\n    id?: string\n    value: string\n    onChange: (value: string) => void\n    rows?: number\n    placeholder?: string\n    className?: string\n  }>\n  \n  Label: React.ComponentType<{\n    htmlFor?: string\n    children: React.ReactNode\n    className?: string\n  }>\n  \n  Button: React.ComponentType<{\n    children: React.ReactNode\n    onClick?: () => void\n    disabled?: boolean\n    type?: 'button' | 'submit'\n    className?: string\n  }>\n  \n  ProgressStep?: React.ComponentType<{\n    currentStep: number\n    totalSteps: number\n    className?: string\n  }>\n}\n```\n\n## 📦 Package Exports\n\nThe package provides two entry points:\n\n- **Main entry** (`@benyue1978/next-dynamic-forms`): Includes Next.js adapters\n- **Core entry** (`@benyue1978/next-dynamic-forms/core`): Core components only, no Next.js dependencies\n\n```tsx\n// For Next.js projects\nimport { createNextJSAdapter } from '@benyue1978/next-dynamic-forms'\n\n// For other React projects\nimport { DynamicForm } from '@benyue1978/next-dynamic-forms/core'\n```\n\n## 🎨 Text Customization\n\n### Default Texts\n\nThe form uses these default texts:\n\n```typescript\n// Button texts\n{\n  previous: 'Previous',\n  next: 'Next', \n  submit: 'Submit',\n  back: 'Back'\n}\n\n// Labels\n{\n  optional: 'Optional',\n  pleaseSelect: 'Please select...'\n}\n\n// Error messages\n{\n  requiredFieldsMissing: 'Please fill in all required fields: {fields}'\n}\n```\n\n### Customizing Texts\n\nYou can override any text by passing the corresponding props:\n\n```tsx\n<DynamicForm\n  config={formConfig}\n  // ... other props\n  buttonTexts={{\n    submit: 'Generate Project',  // Override submit button\n    back: 'Back to Projects'     // Override back button\n  }}\n  labels={{\n    optional: '(Optional)'       // Override optional label\n  }}\n  errorMessages={{\n    requiredFieldsMissing: 'Missing fields: {fields}'  // Override error message\n  }}\n/>\n```\n\n### Internationalization Support\n\nTexts can be internationalized through the i18n adapter:\n\n```tsx\nconst i18nAdapter = {\n  t: (key: string, params?: any) => {\n    const translations = {\n      'form.buttons.submit': '提交',\n      'form.buttons.back': '返回',\n      'form.labels.optional': '(可选)',\n      // ... other translations\n    };\n    return translations[key] || key;\n  }\n};\n```\n\n## 🤔 FAQ\n\n### Q: Does every project need to create an adapter?\n\n**A**: No, but it's recommended for better integration:\n\n1. **Flexibility**: Different projects use different UI libraries and i18n solutions\n2. **Avoid dependency conflicts**: Direct inclusion would cause version locking\n3. **Simplicity**: Adapter code is simple, usually only 10-20 lines\n\n### Q: Can you provide pre-made adapters?\n\n**A**: We provide:\n\n- `createBasicAdapter`: For projects without i18n\n- `createNextJSAdapter`: For Next.js + next-intl projects\n- Core components for custom implementations\n\n### Q: How to reduce boilerplate code?\n\n**A**: You can:\n\n1. Create project-level hooks\n2. Use code snippets/templates\n3. Create internal wrappers for teams\n\n### Q: Can I customize form texts without translation keys?\n\n**A**: Yes! The form now supports direct text customization:\n\n```tsx\n<DynamicForm\n  buttonTexts={{ submit: 'Generate Project' }}\n  labels={{ optional: '(Optional)' }}\n  errorMessages={{ requiredFieldsMissing: 'Missing: {fields}' }}\n/>\n```\n\n## 📖 Documentation\n\nVisit our [interactive documentation](https://next-dynamic-forms.withus.fun) for:\n\n- 📚 [Getting Started Guide](https://next-dynamic-forms.withus.fun)\n- 🎯 [Examples](https://next-dynamic-forms.withus.fun/demos)\n- 🎮 [Interactive Playground](https://next-dynamic-forms.withus.fun/playground)\n\n## 🛠️ Development\n\n```bash\nnpm run test       # Run tests\nnpm run build      # Build package\nnpm run coverage   # Test coverage\n```\n\n## 📄 License\n\nMIT © [benyue1978](https://github.com/benyue1978)\n","readmeFilename":"README.md"}