page.tsx 5.0 KB

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