page.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import Link from "next/link";
  2. import { Code } from "@/components/code";
  3. export const metadata = {
  4. title: "Components | json-render",
  5. };
  6. export default function ComponentsPage() {
  7. return (
  8. <article>
  9. <h1 className="text-3xl font-bold mb-4">Components</h1>
  10. <p className="text-muted-foreground mb-8">
  11. Register React components to render your catalog types.
  12. </p>
  13. <h2 className="text-xl font-semibold mt-12 mb-4">Component Registry</h2>
  14. <p className="text-sm text-muted-foreground mb-4">
  15. Create a registry that maps catalog component types to React components:
  16. </p>
  17. <Code lang="tsx">{`const registry = {
  18. Card: ({ element, children }) => (
  19. <div className="card">
  20. <h2>{element.props.title}</h2>
  21. {element.props.description && (
  22. <p>{element.props.description}</p>
  23. )}
  24. {children}
  25. </div>
  26. ),
  27. Button: ({ element, onAction }) => (
  28. <button onClick={() => onAction(element.props.action, {})}>
  29. {element.props.label}
  30. </button>
  31. ),
  32. };`}</Code>
  33. <h2 className="text-xl font-semibold mt-12 mb-4">Component Props</h2>
  34. <p className="text-sm text-muted-foreground mb-4">
  35. Each component receives these props:
  36. </p>
  37. <Code lang="typescript">{`interface ComponentProps {
  38. element: {
  39. key: string;
  40. type: string;
  41. props: Record<string, unknown>;
  42. children?: UIElement[];
  43. visible?: VisibilityCondition;
  44. validation?: ValidationSchema;
  45. };
  46. children?: React.ReactNode; // Rendered children
  47. onAction: (name: string, params: object) => void;
  48. }`}</Code>
  49. <h2 className="text-xl font-semibold mt-12 mb-4">Using Data Binding</h2>
  50. <p className="text-sm text-muted-foreground mb-4">
  51. Use hooks to read and write data:
  52. </p>
  53. <Code lang="tsx">{`import { useDataValue, useDataBinding } from '@json-render/react';
  54. const Metric = ({ element }) => {
  55. // Read-only value
  56. const value = useDataValue(element.props.valuePath);
  57. return (
  58. <div className="metric">
  59. <span className="label">{element.props.label}</span>
  60. <span className="value">{formatValue(value)}</span>
  61. </div>
  62. );
  63. };
  64. const TextField = ({ element }) => {
  65. // Two-way binding
  66. const [value, setValue] = useDataBinding(element.props.valuePath);
  67. return (
  68. <input
  69. value={value || ''}
  70. onChange={(e) => setValue(e.target.value)}
  71. placeholder={element.props.placeholder}
  72. />
  73. );
  74. };`}</Code>
  75. <h2 className="text-xl font-semibold mt-12 mb-4">Using the Renderer</h2>
  76. <Code lang="tsx">{`import { Renderer } from '@json-render/react';
  77. function App() {
  78. return (
  79. <Renderer
  80. tree={uiTree}
  81. registry={registry}
  82. />
  83. );
  84. }`}</Code>
  85. <h2 className="text-xl font-semibold mt-12 mb-4">Next</h2>
  86. <p className="text-sm text-muted-foreground">
  87. Learn about <Link href="/docs/data-binding" className="text-foreground hover:underline">data binding</Link> for dynamic values.
  88. </p>
  89. </article>
  90. );
  91. }