velloo 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/BUN-LICENSE.md +91 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +9 -0
  4. package/README.md +288 -2
  5. package/THIRD-PARTY-NOTICES.md +467 -0
  6. package/assets/elsewhere-alps-9fqhv029.jpg +0 -0
  7. package/assets/elsewhere-bali-vp60g115.jpg +0 -0
  8. package/assets/elsewhere-forest-xgn23zrj.jpg +0 -0
  9. package/assets/elsewhere-japan-qs7qkbr2.jpg +0 -0
  10. package/assets/elsewhere-kyoto-map-n2bvkrya.svg +1 -0
  11. package/assets/elsewhere-kyoto-qemtn6nk.jpg +0 -0
  12. package/assets/elsewhere-room-g1gaw7cs.jpg +0 -0
  13. package/canvas/apple-touch-icon.png +0 -0
  14. package/canvas/assets/index-BCvDZiBo.css +2 -0
  15. package/canvas/assets/index-ClaBqcaS.js +28 -0
  16. package/canvas/assets/lucide-all-iIF-pmzN.js +1 -0
  17. package/canvas/assets/radix-C3HaOB-d.js +41 -0
  18. package/canvas/assets/react-D0Ec-185.js +9 -0
  19. package/canvas/assets/rolldown-runtime-hePW80VL.js +1 -0
  20. package/canvas/assets/vendor-CKmQ-Zst.js +53 -0
  21. package/canvas/favicon.ico +0 -0
  22. package/canvas/favicon.svg +12 -0
  23. package/canvas/fonts/OFL-1.1.txt +93 -0
  24. package/canvas/fonts/poppins-700.woff2 +0 -0
  25. package/canvas/icon-192.png +0 -0
  26. package/canvas/icon-512.png +0 -0
  27. package/canvas/index.html +22 -0
  28. package/canvas/site.webmanifest +11 -0
  29. package/chunk-08sv3k41.js +4 -0
  30. package/chunk-0fe83yzt.js +2 -0
  31. package/chunk-0t68szgr.js +3 -0
  32. package/chunk-1h55s5he.js +2 -0
  33. package/chunk-2c7jbx46.js +2 -0
  34. package/chunk-2smsg2ct.js +7 -0
  35. package/chunk-308ynsxd.js +2 -0
  36. package/chunk-3e8vez4d.js +1229 -0
  37. package/chunk-40xgcth8.js +63 -0
  38. package/chunk-4dn75m6t.js +3 -0
  39. package/chunk-4fj5tahv.js +3 -0
  40. package/chunk-6nqghjda.js +3 -0
  41. package/chunk-6tx68d90.js +3 -0
  42. package/chunk-6w6ch4ce.js +2 -0
  43. package/chunk-735ezz23.js +86 -0
  44. package/chunk-7eq7nx37.js +7 -0
  45. package/chunk-7eyb8yrf.js +6 -0
  46. package/chunk-80fjfyha.js +86 -0
  47. package/chunk-80r93t2e.js +4 -0
  48. package/chunk-94vx1yb0.js +3 -0
  49. package/chunk-9vg3yafz.js +3 -0
  50. package/chunk-a84n72m2.js +4 -0
  51. package/chunk-ampmdzz4.js +10 -0
  52. package/chunk-avns4dbf.js +2 -0
  53. package/chunk-ayrb3qnm.js +3 -0
  54. package/chunk-bwnvcncx.js +3 -0
  55. package/chunk-ccszg02q.js +5 -0
  56. package/chunk-cvn689d5.js +3 -0
  57. package/chunk-cxe6jjwj.js +3 -0
  58. package/chunk-dg6z4vdd.js +3 -0
  59. package/chunk-dgwjpbp9.js +3 -0
  60. package/chunk-dy41n60j.js +52 -0
  61. package/chunk-ek71z2fv.js +226 -0
  62. package/chunk-er1fxb7d.js +2 -0
  63. package/chunk-eyr8hrzf.js +2 -0
  64. package/chunk-fjbzk4sw.js +3 -0
  65. package/chunk-fsbsksga.js +3 -0
  66. package/chunk-h6gchare.js +3 -0
  67. package/chunk-hcb68zt7.js +85 -0
  68. package/chunk-hggap8fq.js +3 -0
  69. package/chunk-j11fyeqh.js +2 -0
  70. package/chunk-jb21jkp1.js +8 -0
  71. package/chunk-jfx9xjmr.js +18 -0
  72. package/chunk-jr0ss0mm.js +303 -0
  73. package/chunk-jrsknzjt.js +3 -0
  74. package/chunk-jv0xggh0.js +2 -0
  75. package/chunk-k17gfwq3.js +2 -0
  76. package/chunk-mh2pr7cq.js +5 -0
  77. package/chunk-mnapdp1y.js +2 -0
  78. package/chunk-mzhdrawd.js +3 -0
  79. package/chunk-n9gs6yx9.js +2 -0
  80. package/chunk-ngnymg2q.js +3 -0
  81. package/chunk-nwx5700b.js +3 -0
  82. package/chunk-pjtg3wnm.js +4 -0
  83. package/chunk-pp86v6m6.js +3 -0
  84. package/chunk-r22epxz2.js +3 -0
  85. package/chunk-rgasy862.js +5 -0
  86. package/chunk-rpwpeph5.js +3 -0
  87. package/chunk-s23gtejf.js +3 -0
  88. package/chunk-sjgqnykd.js +6 -0
  89. package/chunk-sn3x2m0m.js +6 -0
  90. package/chunk-t448rrfr.js +2 -0
  91. package/chunk-tdsk5wxa.js +451 -0
  92. package/chunk-v40fn08f.js +442 -0
  93. package/chunk-vbk1qhdz.js +3 -0
  94. package/chunk-vdkrbzh1.js +2 -0
  95. package/chunk-vgmr98cv.js +40 -0
  96. package/chunk-vsv8z729.js +6 -0
  97. package/chunk-x4f4k9pp.js +26 -0
  98. package/chunk-xt5ayg7g.js +4 -0
  99. package/chunk-ydhwv29b.js +244 -0
  100. package/chunk-zb6hc1y0.js +2 -0
  101. package/cli.js +3 -0
  102. package/launcher.cjs +97 -0
  103. package/package.json +58 -5
  104. package/pkgs/helpers/src/box.tsx +21 -0
  105. package/pkgs/helpers/src/cn.ts +32 -0
  106. package/pkgs/helpers/src/descriptors.ts +270 -0
  107. package/pkgs/helpers/src/divider.tsx +123 -0
  108. package/pkgs/helpers/src/gradient.tsx +90 -0
  109. package/pkgs/helpers/src/heading.tsx +20 -0
  110. package/pkgs/helpers/src/icon-data.ts +8009 -0
  111. package/pkgs/helpers/src/icon.tsx +53 -0
  112. package/pkgs/helpers/src/image.tsx +111 -0
  113. package/pkgs/helpers/src/index.ts +29 -0
  114. package/pkgs/helpers/src/layer.tsx +61 -0
  115. package/pkgs/helpers/src/lowering.ts +53 -0
  116. package/pkgs/helpers/src/paths.ts +47 -0
  117. package/pkgs/helpers/src/placeholder.tsx +88 -0
  118. package/pkgs/helpers/src/prose.tsx +42 -0
  119. package/pkgs/helpers/src/registry.ts +41 -0
  120. package/pkgs/helpers/src/svg.tsx +62 -0
  121. package/pkgs/helpers/src/text.tsx +16 -0
  122. package/pkgs/provider-antd/src/index.ts +78 -0
  123. package/pkgs/provider-antd/src/intro.ts +14 -0
  124. package/pkgs/provider-antd/src/manifest.ts +439 -0
  125. package/pkgs/provider-antd/src/overlays.ts +176 -0
  126. package/pkgs/provider-antd/src/registry.ts +104 -0
  127. package/pkgs/provider-antd/src/render-pass.ts +43 -0
  128. package/pkgs/provider-antd/src/tailwind-entry.css +21 -0
  129. package/pkgs/provider-antd/src/theme.ts +132 -0
  130. package/pkgs/provider-antd/src/version.ts +8 -0
  131. package/pkgs/provider-chakra/src/index.ts +80 -0
  132. package/pkgs/provider-chakra/src/intro.ts +14 -0
  133. package/pkgs/provider-chakra/src/manifest.ts +421 -0
  134. package/pkgs/provider-chakra/src/overlays.ts +246 -0
  135. package/pkgs/provider-chakra/src/registry.ts +227 -0
  136. package/pkgs/provider-chakra/src/render-pass.ts +55 -0
  137. package/pkgs/provider-chakra/src/tailwind-entry.css +21 -0
  138. package/pkgs/provider-chakra/src/theme.ts +180 -0
  139. package/pkgs/provider-chakra/src/version.ts +8 -0
  140. package/pkgs/provider-mui/src/index.ts +117 -0
  141. package/pkgs/provider-mui/src/intro.ts +12 -0
  142. package/pkgs/provider-mui/src/manifest.ts +263 -0
  143. package/pkgs/provider-mui/src/overlays.ts +124 -0
  144. package/pkgs/provider-mui/src/registry.ts +120 -0
  145. package/pkgs/provider-mui/src/render-pass.ts +36 -0
  146. package/pkgs/provider-mui/src/tailwind-entry.css +21 -0
  147. package/pkgs/provider-mui/src/theme.ts +129 -0
  148. package/pkgs/provider-mui/src/version.ts +8 -0
  149. package/pkgs/provider-none/src/components-inline.tsx +204 -0
  150. package/pkgs/provider-none/src/components.tsx +155 -0
  151. package/pkgs/provider-none/src/index.ts +57 -0
  152. package/pkgs/provider-none/src/intro.ts +18 -0
  153. package/pkgs/provider-none/src/manifest.ts +163 -0
  154. package/pkgs/provider-none/src/registry-inline.ts +36 -0
  155. package/pkgs/provider-none/src/registry.ts +39 -0
  156. package/pkgs/provider-none/src/tailwind-entry.css +57 -0
  157. package/pkgs/provider-none/src/version.ts +10 -0
  158. package/pkgs/schema/src/annotation.ts +120 -0
  159. package/pkgs/schema/src/asset.ts +66 -0
  160. package/pkgs/schema/src/board.ts +71 -0
  161. package/pkgs/schema/src/comment.ts +107 -0
  162. package/pkgs/schema/src/config.ts +185 -0
  163. package/pkgs/schema/src/css-sanitize.ts +56 -0
  164. package/pkgs/schema/src/extension.ts +105 -0
  165. package/pkgs/schema/src/fonts.ts +690 -0
  166. package/pkgs/schema/src/frame.ts +40 -0
  167. package/pkgs/schema/src/icon-name.ts +21 -0
  168. package/pkgs/schema/src/ids.ts +14 -0
  169. package/pkgs/schema/src/index.ts +169 -0
  170. package/pkgs/schema/src/migrate.ts +297 -0
  171. package/pkgs/schema/src/node.ts +229 -0
  172. package/pkgs/schema/src/paths.ts +28 -0
  173. package/pkgs/schema/src/repo.ts +134 -0
  174. package/pkgs/schema/src/screen.ts +30 -0
  175. package/pkgs/schema/src/snippet-resolve.ts +193 -0
  176. package/pkgs/schema/src/snippet.ts +104 -0
  177. package/pkgs/schema/src/svg-sanitize.ts +487 -0
  178. package/pkgs/schema/src/theme.ts +218 -0
  179. package/pkgs/schema/src/typeset.ts +693 -0
  180. package/pkgs/schema/src/validate-ids.ts +46 -0
  181. package/pkgs/schema/src/viewport.ts +8 -0
  182. package/pkgs/shadcn-snapshot/dist/manifest.json +8109 -0
  183. package/pkgs/shadcn-snapshot/src/components/canvas-portal.tsx +55 -0
  184. package/pkgs/shadcn-snapshot/src/components/ui/accordion.tsx +122 -0
  185. package/pkgs/shadcn-snapshot/src/components/ui/alert-dialog.tsx +164 -0
  186. package/pkgs/shadcn-snapshot/src/components/ui/alert.tsx +74 -0
  187. package/pkgs/shadcn-snapshot/src/components/ui/aspect-ratio.tsx +13 -0
  188. package/pkgs/shadcn-snapshot/src/components/ui/attachment.tsx +197 -0
  189. package/pkgs/shadcn-snapshot/src/components/ui/avatar.tsx +100 -0
  190. package/pkgs/shadcn-snapshot/src/components/ui/badge.tsx +50 -0
  191. package/pkgs/shadcn-snapshot/src/components/ui/breadcrumb.tsx +109 -0
  192. package/pkgs/shadcn-snapshot/src/components/ui/bubble.tsx +130 -0
  193. package/pkgs/shadcn-snapshot/src/components/ui/button-group.tsx +82 -0
  194. package/pkgs/shadcn-snapshot/src/components/ui/button.tsx +72 -0
  195. package/pkgs/shadcn-snapshot/src/components/ui/calendar.tsx +229 -0
  196. package/pkgs/shadcn-snapshot/src/components/ui/card.tsx +92 -0
  197. package/pkgs/shadcn-snapshot/src/components/ui/carousel.tsx +235 -0
  198. package/pkgs/shadcn-snapshot/src/components/ui/chart-option.ts +250 -0
  199. package/pkgs/shadcn-snapshot/src/components/ui/chart.tsx +177 -0
  200. package/pkgs/shadcn-snapshot/src/components/ui/checkbox.tsx +41 -0
  201. package/pkgs/shadcn-snapshot/src/components/ui/collapsible.tsx +32 -0
  202. package/pkgs/shadcn-snapshot/src/components/ui/combobox.tsx +196 -0
  203. package/pkgs/shadcn-snapshot/src/components/ui/context-menu.tsx +227 -0
  204. package/pkgs/shadcn-snapshot/src/components/ui/dialog.tsx +131 -0
  205. package/pkgs/shadcn-snapshot/src/components/ui/direction.tsx +24 -0
  206. package/pkgs/shadcn-snapshot/src/components/ui/drawer.tsx +112 -0
  207. package/pkgs/shadcn-snapshot/src/components/ui/dropdown-menu.tsx +205 -0
  208. package/pkgs/shadcn-snapshot/src/components/ui/empty.tsx +98 -0
  209. package/pkgs/shadcn-snapshot/src/components/ui/field.tsx +228 -0
  210. package/pkgs/shadcn-snapshot/src/components/ui/hover-card.tsx +51 -0
  211. package/pkgs/shadcn-snapshot/src/components/ui/input-group.tsx +148 -0
  212. package/pkgs/shadcn-snapshot/src/components/ui/input.tsx +43 -0
  213. package/pkgs/shadcn-snapshot/src/components/ui/item.tsx +187 -0
  214. package/pkgs/shadcn-snapshot/src/components/ui/kbd.tsx +30 -0
  215. package/pkgs/shadcn-snapshot/src/components/ui/label.tsx +25 -0
  216. package/pkgs/shadcn-snapshot/src/components/ui/marker.tsx +71 -0
  217. package/pkgs/shadcn-snapshot/src/components/ui/menubar.tsx +243 -0
  218. package/pkgs/shadcn-snapshot/src/components/ui/message.tsx +89 -0
  219. package/pkgs/shadcn-snapshot/src/components/ui/native-select.tsx +60 -0
  220. package/pkgs/shadcn-snapshot/src/components/ui/navigation-menu.tsx +165 -0
  221. package/pkgs/shadcn-snapshot/src/components/ui/pagination.tsx +117 -0
  222. package/pkgs/shadcn-snapshot/src/components/ui/popover.tsx +66 -0
  223. package/pkgs/shadcn-snapshot/src/components/ui/progress.tsx +35 -0
  224. package/pkgs/shadcn-snapshot/src/components/ui/radio-group.tsx +48 -0
  225. package/pkgs/shadcn-snapshot/src/components/ui/scroll-area.tsx +59 -0
  226. package/pkgs/shadcn-snapshot/src/components/ui/select.tsx +180 -0
  227. package/pkgs/shadcn-snapshot/src/components/ui/separator.tsx +32 -0
  228. package/pkgs/shadcn-snapshot/src/components/ui/sheet.tsx +107 -0
  229. package/pkgs/shadcn-snapshot/src/components/ui/skeleton.tsx +17 -0
  230. package/pkgs/shadcn-snapshot/src/components/ui/slider.tsx +68 -0
  231. package/pkgs/shadcn-snapshot/src/components/ui/sonner.tsx +91 -0
  232. package/pkgs/shadcn-snapshot/src/components/ui/spinner.tsx +21 -0
  233. package/pkgs/shadcn-snapshot/src/components/ui/switch.tsx +41 -0
  234. package/pkgs/shadcn-snapshot/src/components/ui/table.tsx +93 -0
  235. package/pkgs/shadcn-snapshot/src/components/ui/tabs.tsx +84 -0
  236. package/pkgs/shadcn-snapshot/src/components/ui/textarea.tsx +24 -0
  237. package/pkgs/shadcn-snapshot/src/components/ui/toggle-group.tsx +94 -0
  238. package/pkgs/shadcn-snapshot/src/components/ui/toggle.tsx +50 -0
  239. package/pkgs/shadcn-snapshot/src/components/ui/tooltip.tsx +47 -0
  240. package/pkgs/shadcn-snapshot/src/examples.ts +36 -0
  241. package/pkgs/shadcn-snapshot/src/groups.ts +87 -0
  242. package/pkgs/shadcn-snapshot/src/index.ts +43 -0
  243. package/pkgs/shadcn-snapshot/src/lib/utils.ts +4 -0
  244. package/pkgs/shadcn-snapshot/src/manifest.ts +12 -0
  245. package/pkgs/shadcn-snapshot/src/notes.ts +97 -0
  246. package/pkgs/shadcn-snapshot/src/paths.ts +47 -0
  247. package/pkgs/shadcn-snapshot/src/registry-files.ts +293 -0
  248. package/pkgs/shadcn-snapshot/src/registry.ts +631 -0
  249. package/pkgs/shadcn-snapshot/src/shadcn-tailwind.css +632 -0
  250. package/pkgs/shadcn-snapshot/src/tailwind-entry.css +159 -0
  251. package/pkgs/shadcn-snapshot/src/version.ts +8 -0
  252. package/plugins/claude/velloo/.claude-plugin/plugin.json +6 -0
  253. package/plugins/claude/velloo/agents/velloo-design-reviewer.md +33 -0
  254. package/plugins/claude/velloo/agents/velloo-designer.md +39 -0
  255. package/plugins/claude/velloo/commands/design.md +11 -0
  256. package/plugins/claude/velloo/commands/implement.md +10 -0
  257. package/plugins/claude/velloo/commands/review.md +8 -0
  258. package/plugins/gemini/GEMINI.md +31 -0
  259. package/plugins/gemini/commands/velloo/design.toml +10 -0
  260. package/plugins/gemini/commands/velloo/implement.toml +9 -0
  261. package/plugins/gemini/gemini-extension.json +9 -0
  262. package/skills/velloo-brand/SKILL.md +124 -0
  263. package/skills/velloo-design/SKILL.md +144 -0
  264. package/skills/velloo-design-system/SKILL.md +90 -0
  265. package/skills/velloo-implement/SKILL.md +101 -0
  266. package/skills/velloo-logo/SKILL.md +93 -0
  267. package/skills/velloo-setup/SKILL.md +156 -0
@@ -0,0 +1,421 @@
1
+ import type { ComponentDescriptor, Manifest, PropDescriptor } from "@velloo/provider";
2
+
3
+ /**
4
+ * Hand-authored chakra manifest for the shipped registry — curated to the
5
+ * props an agent actually sets (colorScheme/variant/size, the `sx` style
6
+ * channel, children), which reads far better than a generated dump of chakra's
7
+ * vast style-prop surface. Mirrors the MUI/antd adapters' curated-manifest
8
+ * stance; this stays the source of truth.
9
+ */
10
+
11
+ const sx: PropDescriptor = {
12
+ name: "sx",
13
+ type: "SystemStyleObject | undefined",
14
+ optional: true,
15
+ control: "string",
16
+ };
17
+ const children: PropDescriptor = {
18
+ name: "children",
19
+ type: "ReactNode",
20
+ optional: true,
21
+ control: "string",
22
+ };
23
+ const enumProp = (name: string, values: string[], defaultValue?: string): PropDescriptor => ({
24
+ name,
25
+ type: values.map((v) => `"${v}"`).join(" | "),
26
+ optional: true,
27
+ control: "enum",
28
+ enumValues: values,
29
+ defaultValue,
30
+ });
31
+ const str = (name: string, optional = true): PropDescriptor => ({
32
+ name,
33
+ type: "string",
34
+ optional,
35
+ control: "string",
36
+ });
37
+ const num = (name: string): PropDescriptor => ({
38
+ name,
39
+ type: "number",
40
+ optional: true,
41
+ control: "number",
42
+ });
43
+ const bool = (name: string): PropDescriptor => ({
44
+ name,
45
+ type: "boolean",
46
+ optional: true,
47
+ control: "boolean",
48
+ });
49
+ const json = (name: string, type: string): PropDescriptor => ({
50
+ name,
51
+ type,
52
+ optional: true,
53
+ control: "string",
54
+ });
55
+
56
+ const colorScheme = enumProp(
57
+ "colorScheme",
58
+ ["brand", "gray", "red", "orange", "yellow", "green", "teal", "blue", "purple", "pink"],
59
+ "gray",
60
+ );
61
+ const sizeSmMdLg = (defaultValue = "md") =>
62
+ enumProp("size", ["xs", "sm", "md", "lg"], defaultValue);
63
+
64
+ function ui(
65
+ id: string,
66
+ props: PropDescriptor[],
67
+ notes?: string,
68
+ example?: Record<string, unknown>,
69
+ ): ComponentDescriptor {
70
+ return {
71
+ id,
72
+ category: "ui",
73
+ source: "chakra",
74
+ props: [...props, sx],
75
+ designModeNotes: notes,
76
+ example,
77
+ };
78
+ }
79
+
80
+ /** Reused helpers still honor the screen adapter's native sx channel. */
81
+ function helper(
82
+ id: string,
83
+ props: PropDescriptor[],
84
+ notes?: string,
85
+ example?: Record<string, unknown>,
86
+ ): ComponentDescriptor {
87
+ return {
88
+ id,
89
+ category: "ui",
90
+ source: "velloo",
91
+ props: [...props, sx],
92
+ designModeNotes: notes,
93
+ example,
94
+ };
95
+ }
96
+
97
+ export const CHAKRA_MANIFEST: Manifest = [
98
+ // --- layout ---
99
+ ui("Box", [children], "Generic layout primitive; style via sx."),
100
+ ui(
101
+ "Flex",
102
+ [children, json("gap", "number | string"), str("align"), str("justify"), str("direction")],
103
+ "Flex row/column wrapper — `direction`/`align`/`justify`/`gap` are shortcuts; anything else via sx.",
104
+ { gap: 4, align: "center" },
105
+ ),
106
+ ui(
107
+ "Stack",
108
+ [children, num("spacing"), enumProp("direction", ["row", "column"], "column")],
109
+ "Spaced flex layout; `spacing` is the chakra scale (4 = 1rem).",
110
+ { spacing: 4 },
111
+ ),
112
+ ui("HStack", [children, num("spacing")], "Horizontal Stack.", { spacing: 3 }),
113
+ ui("VStack", [children, num("spacing"), str("align")], "Vertical Stack.", {
114
+ spacing: 4,
115
+ align: "stretch",
116
+ }),
117
+ ui(
118
+ "Grid",
119
+ [children, str("templateColumns"), json("gap", "number | string")],
120
+ "CSS grid wrapper; pair with GridItem.",
121
+ { templateColumns: "repeat(3, 1fr)", gap: 6 },
122
+ ),
123
+ ui("GridItem", [children, num("colSpan")], "One cell inside a Grid.", { colSpan: 1 }),
124
+ ui(
125
+ "Container",
126
+ [children, str("maxW"), bool("centerContent")],
127
+ 'Centers + max-widths content. `maxW` takes a size token ("md", "3xl", "container.lg").',
128
+ { maxW: "3xl" },
129
+ ),
130
+ ui("Spacer", [], "Flexible gap inside a Flex/HStack — pushes siblings apart."),
131
+
132
+ // --- surfaces + data display ---
133
+ ui(
134
+ "Card",
135
+ [children, enumProp("variant", ["elevated", "outline", "filled"], "elevated")],
136
+ "Card surface — compose with CardHeader/CardBody/CardFooter children.",
137
+ { variant: "outline" },
138
+ ),
139
+ ui("CardHeader", [children], "Card title area — put a Heading inside."),
140
+ ui("CardBody", [children]),
141
+ ui("CardFooter", [children], "Card action row."),
142
+ ui(
143
+ "Alert",
144
+ [children, enumProp("status", ["info", "success", "warning", "error"], "info")],
145
+ "Inline alert banner — compose with AlertIcon + AlertTitle + AlertDescription children.",
146
+ { status: "info" },
147
+ ),
148
+ ui("AlertIcon", [], "The status icon inside an Alert."),
149
+ ui("AlertTitle", [children], undefined, { children: "Workspace synced" }),
150
+ ui("AlertDescription", [children], undefined, { children: "All changes are saved." }),
151
+ ui(
152
+ "Badge",
153
+ [children, colorScheme, enumProp("variant", ["subtle", "solid", "outline"], "subtle")],
154
+ "Small status label.",
155
+ { colorScheme: "green", children: "Active" },
156
+ ),
157
+ ui(
158
+ "Tag",
159
+ [
160
+ children,
161
+ colorScheme,
162
+ enumProp("variant", ["subtle", "solid", "outline"], "subtle"),
163
+ sizeSmMdLg(),
164
+ ],
165
+ "Label chip — larger than Badge.",
166
+ { colorScheme: "brand", children: "Design" },
167
+ ),
168
+ ui(
169
+ "Avatar",
170
+ [str("name"), str("src"), enumProp("size", ["2xs", "xs", "sm", "md", "lg", "xl", "2xl"], "md")],
171
+ "Avatar — `src` image or initials derived from `name`.",
172
+ { name: "Ada Lovelace" },
173
+ ),
174
+ ui("Divider", [enumProp("orientation", ["horizontal", "vertical"], "horizontal")]),
175
+ ui("Skeleton", [children, json("height", "number | string")], "Loading placeholder block.", {
176
+ height: "20px",
177
+ }),
178
+ ui("Progress", [num("value"), colorScheme, sizeSmMdLg(), bool("hasStripe")], undefined, {
179
+ value: 62,
180
+ colorScheme: "brand",
181
+ }),
182
+ ui(
183
+ "Stat",
184
+ [children],
185
+ "A KPI block — compose with StatLabel + StatNumber + StatHelpText children.",
186
+ ),
187
+ ui("StatLabel", [children], undefined, { children: "Active users" }),
188
+ ui("StatNumber", [children], undefined, { children: "112,893" }),
189
+ ui("StatHelpText", [children], "Secondary line — put a StatArrow inside for a delta.", {
190
+ children: "23% more than last week",
191
+ }),
192
+ ui("StatArrow", [enumProp("type", ["increase", "decrease"], "increase")], undefined, {
193
+ type: "increase",
194
+ }),
195
+
196
+ // --- typography ---
197
+ ui(
198
+ "Heading",
199
+ [
200
+ children,
201
+ enumProp("size", ["xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl"], "xl"),
202
+ str("as"),
203
+ ],
204
+ "A heading — pick `size` for the scale (`as` sets the tag, default h2).",
205
+ { size: "lg", children: "Team analytics" },
206
+ ),
207
+ ui(
208
+ "Text",
209
+ [children, str("fontSize"), str("color"), str("as")],
210
+ 'ALL body text. Tone via sx/props: `color: "chakra-subtle-text"` for muted, theme tokens like "brand.600" work.',
211
+ { fontSize: "sm", color: "chakra-subtle-text", children: "Updated 2 hours ago" },
212
+ ),
213
+
214
+ // --- controls ---
215
+ ui(
216
+ "Button",
217
+ [
218
+ children,
219
+ enumProp("variant", ["solid", "outline", "ghost", "link"], "solid"),
220
+ colorScheme,
221
+ sizeSmMdLg(),
222
+ bool("isDisabled"),
223
+ ],
224
+ 'Action button. `colorScheme="brand"` is the theme\'s primary.',
225
+ { colorScheme: "brand", children: "Submit" },
226
+ ),
227
+ ui(
228
+ "IconButton",
229
+ [
230
+ str("aria-label", false),
231
+ children,
232
+ enumProp("variant", ["solid", "outline", "ghost"], "solid"),
233
+ colorScheme,
234
+ sizeSmMdLg(),
235
+ ],
236
+ "Icon-only button — give it a velloo `Icon` child + an aria-label.",
237
+ { "aria-label": "Settings", variant: "ghost" },
238
+ ),
239
+ ui(
240
+ "Input",
241
+ [
242
+ str("placeholder"),
243
+ str("value"),
244
+ sizeSmMdLg(),
245
+ enumProp("variant", ["outline", "filled", "flushed"], "outline"),
246
+ ],
247
+ undefined,
248
+ { placeholder: "Email address" },
249
+ ),
250
+ ui("Textarea", [str("placeholder"), str("value")], undefined, {
251
+ placeholder: "Tell us more…",
252
+ }),
253
+ ui(
254
+ "Select",
255
+ [str("placeholder"), sizeSmMdLg()],
256
+ "Closed select field in design mode — use `placeholder` for the visible value (option children don't fit design JSON).",
257
+ { placeholder: "Pick a role" },
258
+ ),
259
+ ui("Checkbox", [children, bool("isChecked"), colorScheme], undefined, {
260
+ isChecked: true,
261
+ children: "Remember me",
262
+ }),
263
+ ui("Radio", [children, bool("isChecked"), colorScheme], undefined, {
264
+ isChecked: true,
265
+ children: "Monthly",
266
+ }),
267
+ ui("Switch", [bool("isChecked"), colorScheme, sizeSmMdLg()], undefined, {
268
+ isChecked: true,
269
+ colorScheme: "brand",
270
+ }),
271
+ ui(
272
+ "Slider",
273
+ [children, num("value"), num("min"), num("max"), colorScheme],
274
+ "Compose: Slider > SliderTrack > SliderFilledTrack, + SliderThumb.",
275
+ { value: 30, colorScheme: "brand" },
276
+ ),
277
+ ui("SliderTrack", [children], "The rail — put SliderFilledTrack inside."),
278
+ ui("SliderFilledTrack", []),
279
+ ui("SliderThumb", []),
280
+
281
+ // --- data ---
282
+ ui("TableContainer", [children], "Overflow wrapper — put the Table inside."),
283
+ ui(
284
+ "Table",
285
+ [children, enumProp("variant", ["simple", "striped", "unstyled"], "simple"), sizeSmMdLg()],
286
+ "Data table — compose Thead > Tr > Th and Tbody > Tr > Td children (no data props).",
287
+ { variant: "simple" },
288
+ ),
289
+ ui("Thead", [children]),
290
+ ui("Tbody", [children]),
291
+ ui("Tr", [children]),
292
+ ui("Th", [children, bool("isNumeric")], undefined, { children: "Name" }),
293
+ ui("Td", [children, bool("isNumeric")], undefined, { children: "Ada Lovelace" }),
294
+ ui(
295
+ "Tabs",
296
+ [
297
+ children,
298
+ num("defaultIndex"),
299
+ enumProp("variant", ["line", "enclosed", "soft-rounded", "solid-rounded"], "line"),
300
+ colorScheme,
301
+ ],
302
+ "Compose: Tabs > TabList (Tab children) + TabPanels (TabPanel children). Set `defaultIndex` to pick the visible pane.",
303
+ { defaultIndex: 0, colorScheme: "brand" },
304
+ ),
305
+ ui("TabList", [children]),
306
+ ui("Tab", [children], undefined, { children: "Overview" }),
307
+ ui("TabPanels", [children]),
308
+ ui("TabPanel", [children]),
309
+ ui("List", [children, num("spacing")], "Compose with ListItem children.", { spacing: 2 }),
310
+ ui("ListItem", [children], undefined, { children: "Deploy finished" }),
311
+ ui("Breadcrumb", [children, str("separator")], "Compose: BreadcrumbItem > BreadcrumbLink."),
312
+ ui("BreadcrumbItem", [children, bool("isCurrentPage")]),
313
+ ui("BreadcrumbLink", [children, str("href")], undefined, { href: "#", children: "Home" }),
314
+
315
+ // --- overlay surface — canvas-safe: rendered OPEN + inline in design mode
316
+ // (chakra's own overlays portal and SSR to nothing; their parts need the
317
+ // real parent's context), so build the content directly inside them. ---
318
+ ui(
319
+ "Modal",
320
+ [children, enumProp("size", ["xs", "sm", "md", "lg", "xl", "2xl", "full"], "md")],
321
+ "Modal dialog — renders open + inline in design mode. Compose: Modal > ModalOverlay + ModalContent > ModalHeader/ModalBody/ModalFooter (+ ModalCloseButton). Emitted code needs isOpen/onClose wiring.",
322
+ { size: "md" },
323
+ ),
324
+ ui(
325
+ "ModalOverlay",
326
+ [],
327
+ "The backdrop — renders nothing in design mode (kept for chakra-idiomatic composition).",
328
+ ),
329
+ ui("ModalContent", [children], "The modal surface card."),
330
+ ui("ModalHeader", [children], undefined, { children: "Delete item?" }),
331
+ ui("ModalBody", [children]),
332
+ ui("ModalFooter", [children], "Right-aligned action row."),
333
+ ui("ModalCloseButton", [], "Pinned top-right close button."),
334
+ ui(
335
+ "Drawer",
336
+ [children],
337
+ "A side panel — renders inline as a fixed-width column in design mode. Compose: Drawer > DrawerOverlay + DrawerContent > DrawerHeader/DrawerBody/DrawerFooter.",
338
+ ),
339
+ ui("DrawerOverlay", [], "The backdrop — renders nothing in design mode."),
340
+ ui("DrawerContent", [children], "The drawer surface column."),
341
+ ui("DrawerHeader", [children], undefined, { children: "Filters" }),
342
+ ui("DrawerBody", [children]),
343
+ ui("DrawerFooter", [children]),
344
+ ui(
345
+ "Popover",
346
+ [children],
347
+ "The trigger child renders inline with the surface pinned open below it. Compose: Popover > PopoverTrigger (the trigger) + PopoverContent > PopoverHeader/PopoverBody.",
348
+ ),
349
+ ui("PopoverTrigger", [children], "Wraps the trigger element — renders it as-is."),
350
+ ui("PopoverContent", [children], "The popover surface, pinned open."),
351
+ ui("PopoverHeader", [children], undefined, { children: "Details" }),
352
+ ui("PopoverBody", [children]),
353
+ ui("PopoverArrow", [], "Renders nothing in design mode (kept for chakra-idiomatic composition)."),
354
+ ui(
355
+ "Menu",
356
+ [children],
357
+ "The trigger renders inline with the menu pinned open below it. Compose: Menu > MenuButton (the trigger) + MenuList > MenuItem/MenuDivider.",
358
+ ),
359
+ ui("MenuButton", [children], "The trigger — renders as a chakra Button in design mode.", {
360
+ children: "Actions",
361
+ }),
362
+ ui("MenuList", [children], "The menu surface, pinned open."),
363
+ ui("MenuItem", [children], undefined, { children: "Edit" }),
364
+ ui("MenuDivider", []),
365
+ ui(
366
+ "Tooltip",
367
+ [children, str("label")],
368
+ "The trigger child renders inline; `label` shows beside it as a dark pill in design mode.",
369
+ { label: "Copy to clipboard" },
370
+ ),
371
+
372
+ // Framework-neutral velloo helpers (chakra's @chakra-ui/icons isn't shipped).
373
+ // source:"velloo" — sized/styled via props (NOT sx or Tailwind: a chakra
374
+ // folder has no JIT). `Icon` emits a lucide-react import in codegen.
375
+ helper(
376
+ "Icon",
377
+ [
378
+ { name: "name", type: "string", optional: false, control: "icon" },
379
+ { name: "size", type: "number", optional: true, control: "number" },
380
+ ],
381
+ "A lucide icon — chakra's icon set isn't bundled. Set the pixel `size` prop (not sx). `name` is a lucide id (PascalCase or kebab). Emits a `lucide-react` import.",
382
+ { name: "ArrowRight", size: 20 },
383
+ ),
384
+ helper(
385
+ "Image",
386
+ [
387
+ { name: "src", type: "string", optional: false, control: "string" },
388
+ { name: "alt", type: "string", optional: false, control: "string" },
389
+ ],
390
+ "An image. Use velloo assets (`/assets/…`) or a URL.",
391
+ ),
392
+ helper(
393
+ "Placeholder",
394
+ [{ name: "label", type: "string", optional: true, control: "string" }],
395
+ "A labeled placeholder box for imagery you haven't authored yet (avatars, hero shots).",
396
+ ),
397
+ helper(
398
+ "SVG",
399
+ [
400
+ { name: "content", type: "string", optional: false, control: "string" },
401
+ { name: "viewBox", type: "string", optional: false, control: "string" },
402
+ ],
403
+ "Raw inline SVG markup.",
404
+ ),
405
+ helper("Layer", [children], "An absolutely-positioned overlay layer for stacked composition."),
406
+ helper(
407
+ "Gradient",
408
+ [{ name: "from", type: "string", optional: true, control: "color" }],
409
+ "A gradient fill block.",
410
+ ),
411
+ helper(
412
+ "Prose",
413
+ [
414
+ children,
415
+ { name: "preset", type: "string", optional: true, control: "string" },
416
+ { name: "as", type: "string", optional: true, control: "string" },
417
+ ],
418
+ "A long-form content region. Everything inside — Text, Heading, lists, quotes, code, tables — picks up the theme typeset's proportions and vertical rhythm automatically. `preset` selects a named typeset (see set_typeset). Reach for this for articles, docs, and marketing copy instead of setting sizes block by block.",
419
+ { as: "article" },
420
+ ),
421
+ ];
@@ -0,0 +1,246 @@
1
+ import {
2
+ Box,
3
+ Button as ChakraButton,
4
+ Divider as ChakraDivider,
5
+ CloseButton,
6
+ } from "@chakra-ui/react";
7
+ import { createElement, Fragment, type ReactElement, type ReactNode } from "react";
8
+
9
+ /**
10
+ * Canvas-safe chakra overlays. Chakra's Modal/Drawer portal to `document.body`
11
+ * and render NOTHING in SSR (their Portal is client-only), and every overlay
12
+ * sub-part (ModalHeader, MenuList, PopoverContent, …) reads a context the real
13
+ * parent provides — standalone they throw. Unlike MUI (whose Dialog parts are
14
+ * context-free and re-exported real), chakra needs the WHOLE composition
15
+ * shimmed. The shims keep chakra's composition ids so `emit_code` output is
16
+ * idiomatic chakra (`<Modal><ModalContent>…`), but render everything **open +
17
+ * inline** (in normal flow, no escaping portal, no fixed backdrop) so a
18
+ * screenshot shows the surface; the open/anchor/transition machinery is
19
+ * dropped and the pure-chrome parts (overlay backdrops, popover arrow) render
20
+ * nothing.
21
+ *
22
+ * Mirrors the MUI/antd adapters' overlays and the shadcn snapshot's
23
+ * pinned-open overlay stance.
24
+ */
25
+
26
+ type Props = Record<string, unknown> & { children?: ReactNode };
27
+
28
+ /** Pass-through props every node carries — className for styling, data-node-path for canvas selection. */
29
+ function chrome(props: Props): { className?: string; "data-node-path"?: string } {
30
+ // Only the keys that are actually present: the return type says these may be
31
+ // *absent*, and under `exactOptionalPropertyTypes` an explicit `undefined` is
32
+ // a different thing from an omitted key.
33
+ const className = typeof props.className === "string" ? props.className : undefined;
34
+ const nodePath = props["data-node-path"];
35
+ return {
36
+ ...(className !== undefined ? { className } : {}),
37
+ ...(typeof nodePath === "string" ? { "data-node-path": nodePath } : {}),
38
+ };
39
+ }
40
+
41
+ /** Merge the node's authored `sx` (this provider's style channel) over the shim's base. */
42
+ function mergeSx(baseSx: Record<string, unknown>, sx: unknown): Record<string, unknown> {
43
+ return sx && typeof sx === "object" && !Array.isArray(sx)
44
+ ? { ...baseSx, ...(sx as Record<string, unknown>) }
45
+ : baseSx;
46
+ }
47
+
48
+ function surface(props: Props, baseSx: Record<string, unknown>): ReactElement {
49
+ return createElement(Box, { ...chrome(props), sx: mergeSx(baseSx, props.sx) }, props.children);
50
+ }
51
+
52
+ /** A part that exists only for chakra-composition compatibility (backdrops, arrows) — renders nothing. */
53
+ function nothing(): null {
54
+ return null;
55
+ }
56
+
57
+ // --- Modal ---
58
+
59
+ /** Chakra's modal `size` → a maxW token for the inline surface. */
60
+ const MODAL_MAX_W: Record<string, string> = {
61
+ xs: "xs",
62
+ sm: "sm",
63
+ md: "md",
64
+ lg: "lg",
65
+ xl: "xl",
66
+ "2xl": "2xl",
67
+ full: "100%",
68
+ };
69
+
70
+ /** The modal positioning wrapper, rendered inline (open, no portal). */
71
+ export function Modal(props: Props): ReactElement {
72
+ const maxW = typeof props.size === "string" ? (MODAL_MAX_W[props.size] ?? "md") : "md";
73
+ return surface(props, { w: "100%", maxW, mx: "auto", my: 4 });
74
+ }
75
+
76
+ export const ModalOverlay = nothing;
77
+
78
+ /** The modal surface card. */
79
+ export function ModalContent(props: Props): ReactElement {
80
+ return surface(props, {
81
+ bg: "chakra-body-bg",
82
+ borderRadius: "md",
83
+ boxShadow: "lg",
84
+ overflow: "hidden",
85
+ position: "relative",
86
+ });
87
+ }
88
+
89
+ export function ModalHeader(props: Props): ReactElement {
90
+ return surface(props, { px: 6, py: 4, fontSize: "xl", fontWeight: "semibold" });
91
+ }
92
+
93
+ export function ModalBody(props: Props): ReactElement {
94
+ return surface(props, { px: 6, py: 2 });
95
+ }
96
+
97
+ export function ModalFooter(props: Props): ReactElement {
98
+ return surface(props, { display: "flex", justifyContent: "flex-end", gap: 3, px: 6, py: 4 });
99
+ }
100
+
101
+ /** Chakra's real CloseButton is context-free — pin it where the modal puts it. */
102
+ export function ModalCloseButton(props: Props): ReactElement {
103
+ return createElement(CloseButton, {
104
+ ...chrome(props),
105
+ sx: mergeSx({ position: "absolute", top: 2, insetEnd: 3 }, props.sx),
106
+ });
107
+ }
108
+
109
+ // --- Drawer ---
110
+
111
+ /** A side-drawer panel, rendered inline as a fixed-width column. */
112
+ export function Drawer(props: Props): ReactElement {
113
+ return surface(props, { w: "320px", maxW: "100%", h: "100%" });
114
+ }
115
+
116
+ export const DrawerOverlay = nothing;
117
+
118
+ export function DrawerContent(props: Props): ReactElement {
119
+ return surface(props, {
120
+ bg: "chakra-body-bg",
121
+ h: "100%",
122
+ boxShadow: "lg",
123
+ display: "flex",
124
+ flexDirection: "column",
125
+ });
126
+ }
127
+
128
+ export function DrawerHeader(props: Props): ReactElement {
129
+ return surface(props, { px: 6, py: 4, fontSize: "xl", fontWeight: "semibold" });
130
+ }
131
+
132
+ export function DrawerBody(props: Props): ReactElement {
133
+ return surface(props, { px: 6, py: 2, flex: "1" });
134
+ }
135
+
136
+ export function DrawerFooter(props: Props): ReactElement {
137
+ return surface(props, { display: "flex", justifyContent: "flex-end", gap: 3, px: 6, py: 4 });
138
+ }
139
+
140
+ // --- Popover ---
141
+
142
+ /** The trigger renders inline, the content pinned open below it. */
143
+ export function Popover(props: Props): ReactElement {
144
+ return surface(props, { display: "inline-block" });
145
+ }
146
+
147
+ /** The trigger child as-is (selection lands on the child). */
148
+ export function PopoverTrigger(props: Props): ReactElement {
149
+ return createElement(Fragment, null, props.children);
150
+ }
151
+
152
+ export function PopoverContent(props: Props): ReactElement {
153
+ return surface(props, {
154
+ w: "xs",
155
+ mt: 2,
156
+ bg: "chakra-body-bg",
157
+ borderWidth: "1px",
158
+ borderColor: "chakra-border-color",
159
+ borderRadius: "md",
160
+ boxShadow: "lg",
161
+ });
162
+ }
163
+
164
+ export function PopoverHeader(props: Props): ReactElement {
165
+ return surface(props, { px: 3, py: 2, borderBottomWidth: "1px", fontWeight: "medium" });
166
+ }
167
+
168
+ export function PopoverBody(props: Props): ReactElement {
169
+ return surface(props, { px: 3, py: 2 });
170
+ }
171
+
172
+ export const PopoverArrow = nothing;
173
+
174
+ // --- Menu ---
175
+
176
+ /** The trigger renders inline with the menu surface pinned open below it. */
177
+ export function Menu(props: Props): ReactElement {
178
+ return surface(props, { display: "inline-block" });
179
+ }
180
+
181
+ /** Chakra's real MenuButton needs menu context — a chakra Button stands in. */
182
+ export function MenuButton(props: Props): ReactElement {
183
+ return createElement(
184
+ ChakraButton,
185
+ { ...chrome(props), variant: "outline", sx: mergeSx({}, props.sx) },
186
+ props.children,
187
+ );
188
+ }
189
+
190
+ export function MenuList(props: Props): ReactElement {
191
+ return surface(props, {
192
+ minW: "3xs",
193
+ mt: 2,
194
+ py: 2,
195
+ bg: "chakra-body-bg",
196
+ borderWidth: "1px",
197
+ borderColor: "chakra-border-color",
198
+ borderRadius: "md",
199
+ boxShadow: "lg",
200
+ });
201
+ }
202
+
203
+ export function MenuItem(props: Props): ReactElement {
204
+ return surface(props, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 1.5 });
205
+ }
206
+
207
+ export function MenuDivider(props: Props): ReactElement {
208
+ return createElement(ChakraDivider, { ...chrome(props), sx: mergeSx({ my: 2 }, props.sx) });
209
+ }
210
+
211
+ // --- Tooltip ---
212
+
213
+ /** The trigger child inline; `label` renders beside it as a dark tooltip pill. */
214
+ export function Tooltip(props: Props): ReactElement {
215
+ const label = props.label as ReactNode | undefined;
216
+ return createElement(
217
+ Fragment,
218
+ null,
219
+ props.children,
220
+ label == null
221
+ ? null
222
+ : createElement(
223
+ Box,
224
+ {
225
+ as: "span",
226
+ ...chrome(props),
227
+ sx: mergeSx(
228
+ {
229
+ display: "inline-block",
230
+ bg: "gray.700",
231
+ color: "white",
232
+ borderRadius: "sm",
233
+ px: 2,
234
+ py: 1,
235
+ fontSize: "sm",
236
+ lineHeight: "shorter",
237
+ ml: 2,
238
+ verticalAlign: "middle",
239
+ },
240
+ props.sx,
241
+ ),
242
+ },
243
+ label,
244
+ ),
245
+ );
246
+ }