catalog.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { defineCatalog } from "@json-render/core";
  2. import { schema } from "@json-render/react/schema";
  3. import { z } from "zod";
  4. /**
  5. * A compact, opinionated catalog focused on interactive UI patterns that
  6. * show up well in the devtools panel: state changes, action dispatches,
  7. * input bindings, conditional visibility, and repeated lists.
  8. */
  9. export const catalog = defineCatalog(schema, {
  10. components: {
  11. Card: {
  12. props: z.object({
  13. title: z.string().nullable(),
  14. subtitle: z.string().nullable(),
  15. tone: z
  16. .enum(["default", "accent", "success", "warn", "muted"])
  17. .nullable(),
  18. }),
  19. slots: ["default"],
  20. description: "Container with optional title/subtitle.",
  21. },
  22. Heading: {
  23. props: z.object({
  24. text: z.string(),
  25. level: z.enum(["1", "2", "3"]).nullable(),
  26. }),
  27. description: "Section heading. level defaults to 2.",
  28. },
  29. Text: {
  30. props: z.object({
  31. text: z.string(),
  32. muted: z.boolean().nullable(),
  33. weight: z.enum(["regular", "medium", "bold"]).nullable(),
  34. }),
  35. description: "Paragraph text.",
  36. },
  37. Stack: {
  38. props: z.object({
  39. gap: z.enum(["xs", "sm", "md", "lg"]).nullable(),
  40. }),
  41. slots: ["default"],
  42. description: "Vertical stack with gap.",
  43. },
  44. Row: {
  45. props: z.object({
  46. gap: z.enum(["xs", "sm", "md", "lg"]).nullable(),
  47. align: z.enum(["start", "center", "end", "between"]).nullable(),
  48. }),
  49. slots: ["default"],
  50. description: "Horizontal row with gap.",
  51. },
  52. Grid: {
  53. props: z.object({
  54. columns: z.enum(["2", "3", "4"]).nullable(),
  55. gap: z.enum(["xs", "sm", "md", "lg"]).nullable(),
  56. }),
  57. slots: ["default"],
  58. description: "Multi-column grid layout.",
  59. },
  60. Metric: {
  61. props: z.object({
  62. label: z.string(),
  63. value: z.string(),
  64. delta: z.string().nullable(),
  65. trend: z.enum(["up", "down", "flat"]).nullable(),
  66. }),
  67. description: "Single labelled metric with optional delta + trend.",
  68. },
  69. Badge: {
  70. props: z.object({
  71. label: z.string(),
  72. tone: z
  73. .enum(["default", "accent", "success", "warn", "muted"])
  74. .nullable(),
  75. }),
  76. description: "Small pill-shaped label.",
  77. },
  78. Divider: {
  79. props: z.object({}),
  80. description: "Horizontal rule.",
  81. },
  82. Button: {
  83. props: z.object({
  84. label: z.string(),
  85. variant: z.enum(["primary", "secondary", "ghost"]).nullable(),
  86. size: z.enum(["sm", "md"]).nullable(),
  87. disabled: z.boolean().nullable(),
  88. }),
  89. description:
  90. "Clickable button. Use on.press to trigger actions (setState, pushState, removeState).",
  91. },
  92. TextInput: {
  93. props: z.object({
  94. value: z.string().nullable(),
  95. placeholder: z.string().nullable(),
  96. }),
  97. description:
  98. "Text input. Use { $bindState: '/path' } on value for two-way binding.",
  99. },
  100. Checkbox: {
  101. props: z.object({
  102. label: z.string().nullable(),
  103. checked: z.boolean().nullable(),
  104. }),
  105. description:
  106. "Checkbox. Use { $bindState: '/path' } on checked for two-way binding.",
  107. },
  108. ProgressBar: {
  109. props: z.object({
  110. value: z.number(),
  111. max: z.number().nullable(),
  112. tone: z.enum(["default", "accent", "success", "warn"]).nullable(),
  113. }),
  114. description:
  115. "Horizontal progress bar. value is [0, max]. max defaults to 100.",
  116. },
  117. Callout: {
  118. props: z.object({
  119. title: z.string().nullable(),
  120. text: z.string(),
  121. tone: z.enum(["info", "success", "warn", "tip"]).nullable(),
  122. }),
  123. description: "Highlighted note / tip / warning box.",
  124. },
  125. List: {
  126. props: z.object({}),
  127. slots: ["default"],
  128. description:
  129. "Vertical list container. Pair with repeat to iterate an array.",
  130. },
  131. ListItem: {
  132. props: z.object({
  133. title: z.string(),
  134. description: z.string().nullable(),
  135. meta: z.string().nullable(),
  136. }),
  137. description: "Single list row.",
  138. },
  139. Avatar: {
  140. props: z.object({
  141. initials: z.string(),
  142. tone: z.enum(["default", "accent", "success", "warn"]).nullable(),
  143. }),
  144. description: "Circular avatar with 1-2 initials.",
  145. },
  146. },
  147. actions: {},
  148. });
  149. export type DemoCatalog = typeof catalog;