page.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { Code } from "@/components/code";
  2. export const metadata = {
  3. title: "@json-render/react API | json-render",
  4. };
  5. export default function ReactApiPage() {
  6. return (
  7. <article>
  8. <h1 className="text-3xl font-bold mb-4">@json-render/react</h1>
  9. <p className="text-muted-foreground mb-8">
  10. React components, providers, and hooks.
  11. </p>
  12. <h2 className="text-xl font-semibold mt-12 mb-4">Providers</h2>
  13. <h3 className="text-lg font-semibold mt-8 mb-4">DataProvider</h3>
  14. <Code lang="tsx">{`<DataProvider initialData={object}>
  15. {children}
  16. </DataProvider>`}</Code>
  17. <h3 className="text-lg font-semibold mt-8 mb-4">ActionProvider</h3>
  18. <Code lang="tsx">{`<ActionProvider handlers={Record<string, ActionHandler>}>
  19. {children}
  20. </ActionProvider>
  21. type ActionHandler = (params: Record<string, unknown>) => void | Promise<void>;`}</Code>
  22. <h3 className="text-lg font-semibold mt-8 mb-4">VisibilityProvider</h3>
  23. <Code lang="tsx">{`<VisibilityProvider auth={AuthState}>
  24. {children}
  25. </VisibilityProvider>
  26. interface AuthState {
  27. isSignedIn: boolean;
  28. roles?: string[];
  29. }`}</Code>
  30. <h3 className="text-lg font-semibold mt-8 mb-4">ValidationProvider</h3>
  31. <Code lang="tsx">{`<ValidationProvider functions={Record<string, ValidatorFn>}>
  32. {children}
  33. </ValidationProvider>
  34. type ValidatorFn = (value: unknown, args?: object) => boolean | Promise<boolean>;`}</Code>
  35. <h2 className="text-xl font-semibold mt-12 mb-4">defineRegistry</h2>
  36. <p className="text-sm text-muted-foreground mb-4">
  37. Create a type-safe component registry from a catalog. Components receive{" "}
  38. <code className="text-foreground">props</code>,{" "}
  39. <code className="text-foreground">children</code>,{" "}
  40. <code className="text-foreground">onAction</code>, and{" "}
  41. <code className="text-foreground">loading</code> with catalog-inferred
  42. types.
  43. </p>
  44. <Code lang="tsx">{`import { defineRegistry } from '@json-render/react';
  45. const { registry } = defineRegistry(catalog, {
  46. components: {
  47. Card: ({ props, children }) => <div>{props.title}{children}</div>,
  48. Button: ({ props, onAction }) => (
  49. <button onClick={() => onAction?.({ name: props.action })}>
  50. {props.label}
  51. </button>
  52. ),
  53. },
  54. });
  55. // Pass to <Renderer>
  56. <Renderer spec={spec} registry={registry} />`}</Code>
  57. <h2 className="text-xl font-semibold mt-12 mb-4">Components</h2>
  58. <h3 className="text-lg font-semibold mt-8 mb-4">Renderer</h3>
  59. <Code lang="tsx">{`<Renderer
  60. spec={Spec} // The UI spec to render
  61. registry={Registry} // Component registry (from defineRegistry)
  62. loading={boolean} // Optional loading state
  63. fallback={Component} // Optional fallback for unknown types
  64. />
  65. type Registry = Record<string, React.ComponentType<ComponentRenderProps>>;`}</Code>
  66. <h3 className="text-lg font-semibold mt-8 mb-4">
  67. Component Props (via defineRegistry)
  68. </h3>
  69. <Code lang="tsx">{`interface ComponentContext<P> {
  70. props: P; // Typed props from catalog
  71. children?: React.ReactNode; // Rendered children (for slot components)
  72. onAction?: (action: { name: string; params?: object }) => void;
  73. loading?: boolean;
  74. }`}</Code>
  75. <h2 className="text-xl font-semibold mt-12 mb-4">Hooks</h2>
  76. <h3 className="text-lg font-semibold mt-8 mb-4">useUIStream</h3>
  77. <Code lang="typescript">{`const {
  78. spec, // Spec - current UI state
  79. isStreaming, // boolean - true while streaming
  80. error, // Error | null
  81. send, // (prompt: string) => void
  82. abort, // () => void
  83. } = useUIStream({
  84. api: string, // API endpoint URL
  85. onChunk?: (chunk: string) => void, // Called for each chunk
  86. onFinish?: (spec: Spec) => void, // Called when streaming completes
  87. });`}</Code>
  88. <h3 className="text-lg font-semibold mt-8 mb-4">useData</h3>
  89. <Code lang="typescript">{`const {
  90. data, // Record<string, unknown>
  91. setData, // (data: object) => void
  92. getValue, // (path: string) => unknown
  93. setValue, // (path: string, value: unknown) => void
  94. } = useData();`}</Code>
  95. <h3 className="text-lg font-semibold mt-8 mb-4">useDataValue</h3>
  96. <Code lang="typescript">{`const value = useDataValue(path: string);`}</Code>
  97. <h3 className="text-lg font-semibold mt-8 mb-4">useDataBinding</h3>
  98. <Code lang="typescript">{`const [value, setValue] = useDataBinding(path: string);`}</Code>
  99. <h3 className="text-lg font-semibold mt-8 mb-4">useActions</h3>
  100. <Code lang="typescript">{`const { dispatch } = useActions();
  101. // dispatch(actionName: string, params: object)`}</Code>
  102. <h3 className="text-lg font-semibold mt-8 mb-4">useAction</h3>
  103. <Code lang="typescript">{`const submitForm = useAction('submit_form');
  104. // submitForm(params: object)`}</Code>
  105. <h3 className="text-lg font-semibold mt-8 mb-4">useIsVisible</h3>
  106. <Code lang="typescript">{`const isVisible = useIsVisible(condition?: VisibilityCondition);`}</Code>
  107. <h3 className="text-lg font-semibold mt-8 mb-4">useFieldValidation</h3>
  108. <Code lang="typescript">{`const {
  109. value, // unknown
  110. setValue, // (value: unknown) => void
  111. errors, // string[]
  112. validate, // () => Promise<boolean>
  113. isValid, // boolean
  114. } = useFieldValidation(path: string, checks: ValidationCheck[]);`}</Code>
  115. </article>
  116. );
  117. }