catalog.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { defineCatalog } from "@json-render/core";
  2. import { schema } from "@json-render/react/schema";
  3. import { z } from "zod";
  4. /**
  5. * Web playground component catalog
  6. *
  7. * This defines the components available for AI generation in the playground.
  8. * Components map to implementations in lib/catalog/components.tsx
  9. * Actions map to handlers in lib/catalog/actions.ts
  10. */
  11. export const playgroundCatalog = defineCatalog(schema, {
  12. components: {
  13. // Layout Components
  14. Card: {
  15. props: z.object({
  16. title: z.string().nullable(),
  17. description: z.string().nullable(),
  18. maxWidth: z.enum(["sm", "md", "lg", "full"]).nullable(),
  19. centered: z.boolean().nullable(),
  20. }),
  21. slots: ["default"],
  22. description:
  23. "Container card for content sections. Use for forms/content boxes, NOT for page headers.",
  24. },
  25. Stack: {
  26. props: z.object({
  27. direction: z.enum(["horizontal", "vertical"]).nullable(),
  28. gap: z.enum(["none", "sm", "md", "lg"]).nullable(),
  29. align: z.enum(["start", "center", "end", "stretch"]).nullable(),
  30. justify: z
  31. .enum(["start", "center", "end", "between", "around"])
  32. .nullable(),
  33. }),
  34. slots: ["default"],
  35. description: "Flex container for layouts",
  36. },
  37. Grid: {
  38. props: z.object({
  39. columns: z
  40. .union([
  41. z.literal(1),
  42. z.literal(2),
  43. z.literal(3),
  44. z.literal(4),
  45. z.literal(5),
  46. z.literal(6),
  47. ])
  48. .nullable(),
  49. gap: z.enum(["sm", "md", "lg"]).nullable(),
  50. }),
  51. slots: ["default"],
  52. description: "Grid layout (1-6 columns)",
  53. },
  54. Divider: {
  55. props: z.object({}),
  56. description: "Horizontal separator line",
  57. },
  58. // Form Inputs
  59. Input: {
  60. props: z.object({
  61. label: z.string(),
  62. name: z.string(),
  63. type: z.enum(["text", "email", "password", "number"]).nullable(),
  64. placeholder: z.string().nullable(),
  65. }),
  66. description: "Text input field",
  67. },
  68. Textarea: {
  69. props: z.object({
  70. label: z.string(),
  71. name: z.string(),
  72. placeholder: z.string().nullable(),
  73. rows: z.number().nullable(),
  74. }),
  75. description: "Multi-line text input",
  76. },
  77. Select: {
  78. props: z.object({
  79. label: z.string(),
  80. name: z.string(),
  81. options: z.array(z.string()),
  82. placeholder: z.string().nullable(),
  83. }),
  84. description: "Dropdown select input",
  85. },
  86. Checkbox: {
  87. props: z.object({
  88. label: z.string(),
  89. name: z.string(),
  90. checked: z.boolean().nullable(),
  91. }),
  92. description: "Checkbox input",
  93. },
  94. Radio: {
  95. props: z.object({
  96. label: z.string(),
  97. name: z.string(),
  98. options: z.array(z.string()),
  99. }),
  100. description: "Radio button group",
  101. },
  102. Switch: {
  103. props: z.object({
  104. label: z.string(),
  105. name: z.string(),
  106. checked: z.boolean().nullable(),
  107. }),
  108. description: "Toggle switch input",
  109. },
  110. // Actions
  111. Button: {
  112. props: z.object({
  113. label: z.string(),
  114. variant: z.enum(["primary", "secondary", "danger"]).nullable(),
  115. action: z.string().nullable(),
  116. actionParams: z.record(z.string(), z.unknown()).nullable(),
  117. }),
  118. description:
  119. "Clickable button. Use action to specify the action name and actionParams for parameters.",
  120. },
  121. Link: {
  122. props: z.object({
  123. label: z.string(),
  124. href: z.string(),
  125. }),
  126. description: "Anchor link",
  127. },
  128. // Typography
  129. Heading: {
  130. props: z.object({
  131. text: z.string(),
  132. level: z.enum(["h1", "h2", "h3", "h4"]).nullable(),
  133. }),
  134. description: "Heading text (h1-h4)",
  135. },
  136. Text: {
  137. props: z.object({
  138. text: z.string(),
  139. variant: z.enum(["body", "caption", "muted"]).nullable(),
  140. }),
  141. description: "Paragraph text",
  142. },
  143. // Data Display
  144. Image: {
  145. props: z.object({
  146. alt: z.string(),
  147. width: z.number().nullable(),
  148. height: z.number().nullable(),
  149. }),
  150. description: "Placeholder image (displays alt text in a styled box)",
  151. },
  152. Avatar: {
  153. props: z.object({
  154. src: z.string().nullable(),
  155. name: z.string(),
  156. size: z.enum(["sm", "md", "lg"]).nullable(),
  157. }),
  158. description: "User avatar with fallback initials",
  159. },
  160. Badge: {
  161. props: z.object({
  162. text: z.string(),
  163. variant: z.enum(["default", "success", "warning", "danger"]).nullable(),
  164. }),
  165. description: "Status badge",
  166. },
  167. Alert: {
  168. props: z.object({
  169. title: z.string(),
  170. message: z.string().nullable(),
  171. type: z.enum(["info", "success", "warning", "error"]).nullable(),
  172. }),
  173. description: "Alert banner",
  174. },
  175. Progress: {
  176. props: z.object({
  177. value: z.number(),
  178. max: z.number().nullable(),
  179. label: z.string().nullable(),
  180. }),
  181. description: "Progress bar (value 0-100)",
  182. },
  183. Rating: {
  184. props: z.object({
  185. value: z.number(),
  186. max: z.number().nullable(),
  187. label: z.string().nullable(),
  188. }),
  189. description: "Star rating display",
  190. },
  191. // Charts
  192. BarGraph: {
  193. props: z.object({
  194. title: z.string().nullable(),
  195. data: z.array(
  196. z.object({
  197. label: z.string(),
  198. value: z.number(),
  199. }),
  200. ),
  201. }),
  202. description: "Vertical bar chart",
  203. },
  204. LineGraph: {
  205. props: z.object({
  206. title: z.string().nullable(),
  207. data: z.array(
  208. z.object({
  209. label: z.string(),
  210. value: z.number(),
  211. }),
  212. ),
  213. }),
  214. description: "Line chart with points",
  215. },
  216. },
  217. actions: {
  218. // Demo actions for the playground
  219. buttonClick: {
  220. params: z.object({
  221. message: z.string().nullable(),
  222. }),
  223. description:
  224. "Triggered when a button is clicked. Shows a toast with the message.",
  225. },
  226. formSubmit: {
  227. params: z.object({
  228. formName: z.string().nullable(),
  229. }),
  230. description:
  231. "Triggered when a form is submitted. Shows a toast confirming submission.",
  232. },
  233. linkClick: {
  234. params: z.object({
  235. href: z.string(),
  236. }),
  237. description:
  238. "Triggered when a link is clicked. Shows a toast with the destination.",
  239. },
  240. },
  241. });