page.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import Link from "next/link";
  2. import { Code } from "@/components/code";
  3. export const metadata = {
  4. title: "Validation | json-render",
  5. };
  6. export default function ValidationPage() {
  7. return (
  8. <article>
  9. <h1 className="text-3xl font-bold mb-4">Validation</h1>
  10. <p className="text-muted-foreground mb-8">
  11. Validate form inputs with built-in and custom functions.
  12. </p>
  13. <h2 className="text-xl font-semibold mt-12 mb-4">Built-in Validators</h2>
  14. <p className="text-sm text-muted-foreground mb-4">
  15. json-render includes common validation functions:
  16. </p>
  17. <ul className="list-disc list-inside text-sm text-muted-foreground space-y-1 mb-4">
  18. <li>
  19. <code className="text-foreground">required</code> — Value must be
  20. non-empty
  21. </li>
  22. <li>
  23. <code className="text-foreground">email</code> — Valid email format
  24. </li>
  25. <li>
  26. <code className="text-foreground">minLength</code> — Minimum string
  27. length
  28. </li>
  29. <li>
  30. <code className="text-foreground">maxLength</code> — Maximum string
  31. length
  32. </li>
  33. <li>
  34. <code className="text-foreground">pattern</code> — Match a regex
  35. pattern
  36. </li>
  37. <li>
  38. <code className="text-foreground">min</code> — Minimum numeric value
  39. </li>
  40. <li>
  41. <code className="text-foreground">max</code> — Maximum numeric value
  42. </li>
  43. </ul>
  44. <h2 className="text-xl font-semibold mt-12 mb-4">
  45. Using Validation in JSON
  46. </h2>
  47. <Code lang="json">{`{
  48. "type": "TextField",
  49. "props": {
  50. "label": "Email",
  51. "valuePath": "/form/email",
  52. "checks": [
  53. { "fn": "required", "message": "Email is required" },
  54. { "fn": "email", "message": "Invalid email format" }
  55. ],
  56. "validateOn": "blur"
  57. }
  58. }`}</Code>
  59. <h2 className="text-xl font-semibold mt-12 mb-4">
  60. Validation with Parameters
  61. </h2>
  62. <Code lang="json">{`{
  63. "type": "TextField",
  64. "props": {
  65. "label": "Password",
  66. "valuePath": "/form/password",
  67. "checks": [
  68. { "fn": "required", "message": "Password is required" },
  69. {
  70. "fn": "minLength",
  71. "args": { "length": 8 },
  72. "message": "Password must be at least 8 characters"
  73. },
  74. {
  75. "fn": "pattern",
  76. "args": { "pattern": "[A-Z]" },
  77. "message": "Must contain at least one uppercase letter"
  78. }
  79. ]
  80. }
  81. }`}</Code>
  82. <h2 className="text-xl font-semibold mt-12 mb-4">
  83. Custom Validation Functions
  84. </h2>
  85. <p className="text-sm text-muted-foreground mb-4">
  86. Define custom validators in your catalog:
  87. </p>
  88. <Code lang="typescript">{`const catalog = createCatalog({
  89. components: { /* ... */ },
  90. validationFunctions: {
  91. isValidPhone: {
  92. description: 'Validates phone number format',
  93. },
  94. isUniqueEmail: {
  95. description: 'Checks if email is not already registered',
  96. },
  97. },
  98. });`}</Code>
  99. <p className="text-sm text-muted-foreground mb-4">
  100. Then implement them in your ValidationProvider:
  101. </p>
  102. <Code lang="tsx">{`import { ValidationProvider } from '@json-render/react';
  103. function App() {
  104. const customValidators = {
  105. isValidPhone: (value) => {
  106. const phoneRegex = /^\\+?[1-9]\\d{1,14}$/;
  107. return phoneRegex.test(value);
  108. },
  109. isUniqueEmail: async (value) => {
  110. const response = await fetch(\`/api/check-email?email=\${value}\`);
  111. const { available } = await response.json();
  112. return available;
  113. },
  114. };
  115. return (
  116. <ValidationProvider functions={customValidators}>
  117. {/* Your UI */}
  118. </ValidationProvider>
  119. );
  120. }`}</Code>
  121. <h2 className="text-xl font-semibold mt-12 mb-4">Using in Components</h2>
  122. <Code lang="tsx">{`import { useFieldValidation } from '@json-render/react';
  123. function TextField({ element }) {
  124. const { value, setValue, errors, validate } = useFieldValidation(
  125. element.props.valuePath,
  126. element.props.checks
  127. );
  128. return (
  129. <div>
  130. <label>{element.props.label}</label>
  131. <input
  132. value={value || ''}
  133. onChange={(e) => setValue(e.target.value)}
  134. onBlur={() => validate()}
  135. />
  136. {errors.map((error, i) => (
  137. <p key={i} className="text-red-500 text-sm">{error}</p>
  138. ))}
  139. </div>
  140. );
  141. }`}</Code>
  142. <h2 className="text-xl font-semibold mt-12 mb-4">Validation Timing</h2>
  143. <p className="text-sm text-muted-foreground mb-4">
  144. Control when validation runs with{" "}
  145. <code className="text-foreground">validateOn</code>:
  146. </p>
  147. <ul className="list-disc list-inside text-sm text-muted-foreground space-y-1">
  148. <li>
  149. <code className="text-foreground">change</code> — Validate on every
  150. input change
  151. </li>
  152. <li>
  153. <code className="text-foreground">blur</code> — Validate when field
  154. loses focus
  155. </li>
  156. <li>
  157. <code className="text-foreground">submit</code> — Validate only on
  158. form submission
  159. </li>
  160. </ul>
  161. <h2 className="text-xl font-semibold mt-12 mb-4">Next</h2>
  162. <p className="text-sm text-muted-foreground">
  163. Learn about{" "}
  164. <Link href="/docs/ai-sdk" className="text-foreground hover:underline">
  165. AI SDK integration
  166. </Link>
  167. .
  168. </p>
  169. </article>
  170. );
  171. }