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,84 @@
1
+ // Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/tabs).
2
+ // Snapshot version: see packages/shadcn-snapshot/package.json#snapshotVersion.
3
+ // Regenerate with `bun run vendor` — do not hand-edit unless you are adding a
4
+ // canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
5
+ "use client";
6
+
7
+ import { cva, type VariantProps } from "class-variance-authority";
8
+ import { Tabs as TabsPrimitive } from "radix-ui";
9
+ import type * as React from "react";
10
+
11
+ import { cn } from "../../lib/utils.ts";
12
+
13
+ function Tabs({
14
+ className,
15
+ orientation = "horizontal",
16
+ ...props
17
+ }: React.ComponentProps<typeof TabsPrimitive.Root>) {
18
+ return (
19
+ <TabsPrimitive.Root
20
+ data-slot="tabs"
21
+ data-orientation={orientation}
22
+ className={cn("group/tabs flex gap-2 data-horizontal:flex-col", className)}
23
+ {...props}
24
+ />
25
+ );
26
+ }
27
+
28
+ const tabsListVariants = cva(
29
+ "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
30
+ {
31
+ variants: {
32
+ variant: {
33
+ default: "bg-muted",
34
+ line: "gap-1 bg-transparent",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ },
40
+ },
41
+ );
42
+
43
+ function TabsList({
44
+ className,
45
+ variant = "default",
46
+ ...props
47
+ }: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {
48
+ return (
49
+ <TabsPrimitive.List
50
+ data-slot="tabs-list"
51
+ data-variant={variant}
52
+ className={cn(tabsListVariants({ variant }), className)}
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+
58
+ function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
59
+ return (
60
+ <TabsPrimitive.Trigger
61
+ data-slot="tabs-trigger"
62
+ className={cn(
63
+ "relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
64
+ "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
65
+ "data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
66
+ "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
67
+ className,
68
+ )}
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
75
+ return (
76
+ <TabsPrimitive.Content
77
+ data-slot="tabs-content"
78
+ className={cn("flex-1 text-sm outline-none", className)}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ export { Tabs, TabsContent, TabsList, TabsTrigger, tabsListVariants };
@@ -0,0 +1,24 @@
1
+ // Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/textarea).
2
+ // Snapshot version: see packages/shadcn-snapshot/package.json#snapshotVersion.
3
+ // Canvas-safe: same contract as Input — designs ship a `value` with no handler
4
+ // to show populated copy, and React warns about a controlled field it can never
5
+ // update, so `value` without `onChange` opts into `readOnly`.
6
+ import type * as React from "react";
7
+
8
+ import { cn } from "../../lib/utils.ts";
9
+
10
+ export function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
11
+ const isStaticControlled =
12
+ props.value !== undefined && props.onChange === undefined && props.readOnly === undefined;
13
+ return (
14
+ <textarea
15
+ data-slot="textarea"
16
+ className={cn(
17
+ "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
18
+ className,
19
+ )}
20
+ {...props}
21
+ readOnly={isStaticControlled ? true : props.readOnly}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,94 @@
1
+ // Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/toggle-group).
2
+ // Snapshot version: see packages/shadcn-snapshot/package.json#snapshotVersion.
3
+ // Canvas-safe: the group's props are relaxed off Radix's `type`-discriminated
4
+ // union, and `type` defaults, so a design that only names the items still
5
+ // renders.
6
+ "use client";
7
+
8
+ import type { VariantProps } from "class-variance-authority";
9
+ import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
10
+ import * as React from "react";
11
+
12
+ import { cn } from "../../lib/utils.ts";
13
+ import { toggleVariants } from "./toggle.tsx";
14
+
15
+ const ToggleGroupContext = React.createContext<
16
+ VariantProps<typeof toggleVariants> & {
17
+ spacing?: number;
18
+ orientation?: "horizontal" | "vertical";
19
+ }
20
+ >({
21
+ size: "default",
22
+ variant: "default",
23
+ spacing: 2,
24
+ orientation: "horizontal",
25
+ });
26
+
27
+ /**
28
+ * Radix discriminates the Root's props on `type` — `value` is a string for
29
+ * `"single"` and an array for `"multiple"` — which is user-hostile to thread
30
+ * through MCP. The wrapper takes a permissive passthrough instead: a
31
+ * design-mode group only has to render.
32
+ */
33
+ export function ToggleGroup({
34
+ className,
35
+ variant,
36
+ size,
37
+ spacing = 2,
38
+ orientation = "horizontal",
39
+ type = "single",
40
+ children,
41
+ ...props
42
+ // biome-ignore lint/suspicious/noExplicitAny: discriminated radix props are user-hostile in design mode
43
+ }: any) {
44
+ return (
45
+ <ToggleGroupPrimitive.Root
46
+ data-slot="toggle-group"
47
+ data-variant={variant}
48
+ data-size={size}
49
+ data-spacing={spacing}
50
+ data-orientation={orientation}
51
+ type={type as "single"}
52
+ style={{ "--gap": spacing } as React.CSSProperties}
53
+ className={cn(
54
+ "group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch",
55
+ className,
56
+ )}
57
+ {...props}
58
+ >
59
+ <ToggleGroupContext.Provider value={{ variant, size, spacing, orientation }}>
60
+ {children}
61
+ </ToggleGroupContext.Provider>
62
+ </ToggleGroupPrimitive.Root>
63
+ );
64
+ }
65
+
66
+ export function ToggleGroupItem({
67
+ className,
68
+ children,
69
+ variant = "default",
70
+ size = "default",
71
+ ...props
72
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>) {
73
+ const context = React.useContext(ToggleGroupContext);
74
+
75
+ return (
76
+ <ToggleGroupPrimitive.Item
77
+ data-slot="toggle-group-item"
78
+ data-variant={context.variant || variant}
79
+ data-size={context.size || size}
80
+ data-spacing={context.spacing}
81
+ className={cn(
82
+ "shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
83
+ toggleVariants({
84
+ variant: context.variant || variant,
85
+ size: context.size || size,
86
+ }),
87
+ className,
88
+ )}
89
+ {...props}
90
+ >
91
+ {children}
92
+ </ToggleGroupPrimitive.Item>
93
+ );
94
+ }
@@ -0,0 +1,50 @@
1
+ // Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/toggle).
2
+ // Snapshot version: see packages/shadcn-snapshot/package.json#snapshotVersion.
3
+ // Regenerate with `bun run vendor` — do not hand-edit unless you are adding a
4
+ // canvas adaptation, in which case add the id to vendor.ts's ADAPTED set.
5
+ "use client";
6
+
7
+ import { cva, type VariantProps } from "class-variance-authority";
8
+ import { Toggle as TogglePrimitive } from "radix-ui";
9
+ import type * as React from "react";
10
+
11
+ import { cn } from "../../lib/utils.ts";
12
+
13
+ const toggleVariants = cva(
14
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
15
+ {
16
+ variants: {
17
+ variant: {
18
+ default: "bg-transparent",
19
+ outline: "border border-input bg-transparent hover:bg-muted",
20
+ },
21
+ size: {
22
+ default:
23
+ "h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
24
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
25
+ lg: "h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ variant: "default",
30
+ size: "default",
31
+ },
32
+ },
33
+ );
34
+
35
+ function Toggle({
36
+ className,
37
+ variant = "default",
38
+ size = "default",
39
+ ...props
40
+ }: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) {
41
+ return (
42
+ <TogglePrimitive.Root
43
+ data-slot="toggle"
44
+ className={cn(toggleVariants({ variant, size, className }))}
45
+ {...props}
46
+ />
47
+ );
48
+ }
49
+
50
+ export { Toggle, toggleVariants };
@@ -0,0 +1,47 @@
1
+ // Vendored from shadcn-ui (https://ui.shadcn.com/docs/components/radix/tooltip).
2
+ // Snapshot version: see packages/shadcn-snapshot/package.json#snapshotVersion.
3
+ // Canvas-safe: see ../canvas-portal.tsx.
4
+ "use client";
5
+
6
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
7
+ import type * as React from "react";
8
+ import { cn } from "../../lib/utils.ts";
9
+ import { inlineOpenAttrs, pinOpenInDesignMode } from "../canvas-portal.tsx";
10
+
11
+ export function TooltipProvider({
12
+ ...props
13
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
14
+ return <TooltipPrimitive.Provider data-slot="tooltip-provider" {...props} />;
15
+ }
16
+
17
+ export function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
18
+ return (
19
+ <TooltipPrimitive.Provider>
20
+ <TooltipPrimitive.Root data-slot="tooltip" {...pinOpenInDesignMode(props)} />
21
+ </TooltipPrimitive.Provider>
22
+ );
23
+ }
24
+
25
+ export function TooltipTrigger({
26
+ ...props
27
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
28
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
29
+ }
30
+
31
+ export function TooltipContent({
32
+ className,
33
+ sideOffset: _sideOffset,
34
+ ...props
35
+ }: React.ComponentProps<"div"> & { sideOffset?: number }) {
36
+ return (
37
+ <div
38
+ data-slot="tooltip-content"
39
+ {...inlineOpenAttrs()}
40
+ className={cn(
41
+ "z-50 inline-flex w-fit max-w-xs items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm",
42
+ className,
43
+ )}
44
+ {...props}
45
+ />
46
+ );
47
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Canonical usage examples merged into the generated manifest by
3
+ * build.ts. Only components whose prop *shapes* aren't obvious from
4
+ * names need one — the goal is that an agent can copy the example,
5
+ * swap values, and get a correct render on the first try.
6
+ *
7
+ * Covers the shadcn-sourced components only; the velloo helpers carry
8
+ * their examples inside `@velloo/helpers`' canonical descriptors.
9
+ */
10
+ export const COMPONENT_EXAMPLES: Record<string, Record<string, unknown>> = {
11
+ Chart: {
12
+ // Single series: `data: [{ x, y }]`. Multi-series: `categories` +
13
+ // `series: [{ name, data: number[] }]` (legend auto-on). `kind`:
14
+ // bar | line | area | pie | scatter. `tickFormat`: number | compact |
15
+ // currency | percent. `xLabel`/`yLabel` add axis titles. `color`
16
+ // (single-series): primary | accent | muted — theme tokens, so charts
17
+ // flip under dark mode.
18
+ kind: "bar",
19
+ categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
20
+ series: [
21
+ { name: "Revenue", data: [4200, 5800, 5100, 7300, 6400] },
22
+ { name: "Refunds", data: [400, 600, 350, 720, 500] },
23
+ ],
24
+ yLabel: "USD",
25
+ tickFormat: "compact",
26
+ className: "h-64 w-full",
27
+ },
28
+ Button: { variant: "outline", size: "sm", children: "Action" },
29
+ Badge: { variant: "secondary", children: "Label" },
30
+ Progress: { value: 64, className: "h-2" },
31
+ Avatar: { className: "size-9" },
32
+ // `ratio` is width/height as a number, not the "16:9" string it reads as.
33
+ AspectRatio: { ratio: 16 / 9 },
34
+ // Renders a list, so it takes objects rather than the string it looks like.
35
+ FieldError: { errors: [{ message: "Enter a valid email address." }] },
36
+ };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Which shelf each shadcn family sits on, keyed by its source file — the same
3
+ * key `build.ts` already resolves per component, so a newly vendored family
4
+ * gets grouped by adding one line here rather than by being re-listed
5
+ * somewhere downstream.
6
+ *
7
+ * A family with no entry falls into the catch-all bucket, which is why the
8
+ * manifest test asserts this table covers every vendored file: the previous
9
+ * arrangement kept the grouping in the canvas sidebar, where 20 new families
10
+ * were silently unbrowsable because nothing failed when the list went stale.
11
+ */
12
+ import type { ComponentGroup } from "@velloo/provider";
13
+
14
+ export const FAMILY_GROUPS: Record<string, ComponentGroup> = {
15
+ button: "actions",
16
+ "button-group": "actions",
17
+ toggle: "actions",
18
+ "toggle-group": "actions",
19
+
20
+ input: "forms",
21
+ textarea: "forms",
22
+ label: "forms",
23
+ checkbox: "forms",
24
+ "radio-group": "forms",
25
+ switch: "forms",
26
+ slider: "forms",
27
+ select: "forms",
28
+ "native-select": "forms",
29
+ combobox: "forms",
30
+ calendar: "forms",
31
+ field: "forms",
32
+ "input-group": "forms",
33
+
34
+ avatar: "display",
35
+ badge: "display",
36
+ card: "display",
37
+ skeleton: "display",
38
+ table: "display",
39
+ item: "display",
40
+ kbd: "display",
41
+
42
+ alert: "feedback",
43
+ progress: "feedback",
44
+ sonner: "feedback",
45
+ spinner: "feedback",
46
+ empty: "feedback",
47
+
48
+ tabs: "navigation",
49
+ breadcrumb: "navigation",
50
+ pagination: "navigation",
51
+ accordion: "navigation",
52
+ "navigation-menu": "navigation",
53
+ menubar: "navigation",
54
+
55
+ dialog: "overlays",
56
+ "alert-dialog": "overlays",
57
+ sheet: "overlays",
58
+ drawer: "overlays",
59
+ popover: "overlays",
60
+ "dropdown-menu": "overlays",
61
+ "context-menu": "overlays",
62
+ "hover-card": "overlays",
63
+ tooltip: "overlays",
64
+ collapsible: "overlays",
65
+
66
+ "scroll-area": "layout",
67
+ separator: "layout",
68
+ carousel: "layout",
69
+ "aspect-ratio": "layout",
70
+
71
+ chart: "visuals",
72
+
73
+ attachment: "chat",
74
+ bubble: "chat",
75
+ message: "chat",
76
+ marker: "chat",
77
+ };
78
+
79
+ /**
80
+ * Families that are intentionally ungrouped: real exports an agent can name,
81
+ * but not components anyone browses for. Listed rather than omitted so the
82
+ * coverage test can tell "decided" from "forgotten".
83
+ */
84
+ export const UNGROUPED_FAMILIES: ReadonlySet<string> = new Set([
85
+ // Context provider for RTL — wraps a tree, renders no UI of its own.
86
+ "direction",
87
+ ]);
@@ -0,0 +1,43 @@
1
+ import { type FrameworkAdapter, type Manifest, TAILWIND_CLASSNAME } from "@velloo/provider";
2
+ import { componentsDir, entryCssPath, manifestPath, snapshotVersion } from "./paths.ts";
3
+ import { registry } from "./registry.ts";
4
+
5
+ export type { ComponentDescriptor, Manifest, PropDescriptor } from "./manifest.ts";
6
+ export { componentsDir, entryCssPath, snapshotVersion } from "./paths.ts";
7
+ export { registry } from "./registry.ts";
8
+
9
+ /**
10
+ * Prop manifest extracted from the vendored sources via ts-morph at build time.
11
+ */
12
+ export async function loadManifest(): Promise<Manifest> {
13
+ const file = Bun.file(manifestPath);
14
+ if (!(await file.exists())) {
15
+ throw new Error(
16
+ `@velloo/shadcn-snapshot: dist/manifest.json missing. Run \`bun run build\` in packages/shadcn-snapshot.`,
17
+ );
18
+ }
19
+ return (await file.json()) as Manifest;
20
+ }
21
+
22
+ /**
23
+ * Build a `ComponentProvider` instance for this snapshot. Optionally
24
+ * overrides the on-disk `componentsDir` when the user installed the
25
+ * snapshot files outside the binary (in-repo or cache mode) — the
26
+ * runtime registry stays bundled with velloo (so what the canvas
27
+ * renders is byte-identical across folders), but the JIT scan target
28
+ * follows the install location so user customizations contribute to
29
+ * the compiled CSS.
30
+ */
31
+ export function createProvider(opts: { componentsDir?: string } = {}): FrameworkAdapter {
32
+ return {
33
+ id: "shadcn-react",
34
+ version: snapshotVersion,
35
+ componentsDir: opts.componentsDir ?? componentsDir,
36
+ styleEntryPath: entryCssPath,
37
+ registry,
38
+ loadManifest,
39
+ label: `shadcn-react ${snapshotVersion}`,
40
+ styleChannel: TAILWIND_CLASSNAME,
41
+ styleChannels: ["tailwind-classname"],
42
+ };
43
+ }
@@ -0,0 +1,4 @@
1
+ // Upstream shadcn's `cn`, re-pointed at velloo's configured tailwind-merge: a
2
+ // design folder's theme generates the typeset utilities (`text-h1`, …), which
3
+ // the stock config would misgroup as colors and silently drop.
4
+ export { cn } from "@velloo/helpers";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Manifest types moved to `@velloo/provider`. This module re-exports them
3
+ * so existing imports (`from "@velloo/shadcn-snapshot"`) keep working
4
+ * through the migration; consumers should prefer importing from
5
+ * `@velloo/provider` going forward.
6
+ */
7
+ export type {
8
+ ComponentDescriptor,
9
+ ControlType,
10
+ Manifest,
11
+ PropDescriptor,
12
+ } from "@velloo/provider";
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Per-component `designModeNotes`, merged into the generated manifest by
3
+ * build.ts.
4
+ *
5
+ * Scoped to one job: telling an agent *when to reach for a component instead
6
+ * of building the same thing out of `Box` and `Text`*. Prop names already say
7
+ * what a component accepts and `example` shows the shapes; neither says that
8
+ * a label/control/help-text stack is what `Field` is for. That gap matters
9
+ * most for the families that postdate most models' training data (Field,
10
+ * InputGroup, Item, Empty, ButtonGroup, Spinner, Kbd, the chat set), which
11
+ * otherwise get hand-rolled — so notes go on family roots, and on the handful
12
+ * of sub-pieces whose own role isn't obvious from the name.
13
+ *
14
+ * Keep them to a couple of sentences. The composition shape belongs here as a
15
+ * JSX sketch because `compose` takes exactly that syntax.
16
+ */
17
+ export const COMPONENT_NOTES: Record<string, string> = {
18
+ // ---- Forms -------------------------------------------------------------
19
+ Field:
20
+ "The form-field scaffold — reach for this instead of stacking Label + Input + help text by hand. " +
21
+ "`<Field><FieldLabel htmlFor='email'>Email</FieldLabel><Input id='email'/>" +
22
+ "<FieldDescription>We never share it.</FieldDescription></Field>`. " +
23
+ 'Set `orientation="horizontal"` to put the label beside the control (checkbox/switch rows), ' +
24
+ "`FieldGroup` to stack several fields with consistent spacing, and `FieldSet` + `FieldLegend` for a titled section.",
25
+ FieldError:
26
+ "Renders a list, so `errors` takes objects: `[{ message: 'Enter a valid email.' }]` — not a string. " +
27
+ "Place it last inside a `Field`.",
28
+ FieldSeparator: "An 'or' divider between fields; put the label in `children`.",
29
+ InputGroup:
30
+ "An input with something attached inside its border — a leading icon, a trailing unit, a submit button. " +
31
+ "`<InputGroup><InputGroupAddon><Icon name='search'/></InputGroupAddon><InputGroupInput placeholder='Search'/></InputGroup>`. " +
32
+ "Use `InputGroupInput`/`InputGroupTextarea` rather than a bare `Input` inside it, and " +
33
+ '`InputGroupAddon align="inline-end"` for the trailing slot. This is the component for search bars and prefixed URL fields.',
34
+ NativeSelect:
35
+ "A real `<select>` — one tap-to-open list on mobile, and it renders faithfully in design mode. " +
36
+ "Prefer it over `Select` for plain option lists; `Select` is the Radix listbox, needed only for rich/custom option rows. " +
37
+ "Children are `NativeSelectOption` (and `NativeSelectOptGroup`).",
38
+ Combobox:
39
+ "Type-to-filter selection: `ComboboxInput` + `ComboboxList`/`ComboboxItem`, with `ComboboxChips` for multi-select. " +
40
+ "In design mode the list renders open and inline so you can see it; filtering does not run.",
41
+
42
+ // ---- Actions -----------------------------------------------------------
43
+ ButtonGroup:
44
+ "Joins adjacent buttons into one segmented control — shared borders, rounded only on the ends. " +
45
+ "Use it instead of a flex `Box` with `gap`, which leaves them as separate buttons. " +
46
+ "`ButtonGroupText` adds a static label segment; `ButtonGroupSeparator` divides groups.",
47
+
48
+ // ---- Display -----------------------------------------------------------
49
+ Item:
50
+ "One row of a list — the generic list-row surface, and the right building block for settings rows, " +
51
+ "notification lists and file lists that would otherwise be a hand-built flex `Box`. " +
52
+ "`<Item><ItemMedia><Icon name='file'/></ItemMedia><ItemContent><ItemTitle>Report.pdf</ItemTitle>" +
53
+ "<ItemDescription>2.4 MB</ItemDescription></ItemContent><ItemActions><Button/></ItemActions></Item>`. " +
54
+ "`ItemGroup` wraps a list; use `Card` only for actual card surfaces.",
55
+ Kbd: "A keyboard key cap (`⌘`, `K`). `KbdGroup` sets a chord — reach for it in shortcut hints and command-menu rows.",
56
+
57
+ // ---- Feedback ----------------------------------------------------------
58
+ Empty:
59
+ "The empty-state surface: centred icon, heading, explanation, action. " +
60
+ "`<Empty><EmptyHeader><EmptyMedia><Icon name='inbox'/></EmptyMedia><EmptyTitle>No invoices</EmptyTitle>" +
61
+ "<EmptyDescription>Create one to get started.</EmptyDescription></EmptyHeader><EmptyContent><Button/></EmptyContent></Empty>`. " +
62
+ "Use it for any 'nothing here yet' panel rather than centring text in a `Box`.",
63
+ Spinner:
64
+ "An inline loading indicator. Size it with a class (`size-4`) and pair it with `Skeleton` for block-level placeholders.",
65
+
66
+ // ---- Overlays ----------------------------------------------------------
67
+ Drawer:
68
+ "A sheet that slides from an edge with a drag handle — the mobile-idiomatic bottom sheet. " +
69
+ "For a desktop side panel prefer `Sheet`; the two are otherwise the same shape. " +
70
+ "Rendered open and inline in design mode.",
71
+ HoverCard:
72
+ "A rich preview shown on hover (user cards, link previews) — not a `Tooltip`, which is for a short text hint. " +
73
+ "Rendered open and inline in design mode.",
74
+ ContextMenu:
75
+ "The right-click menu. Same item vocabulary as `DropdownMenu`, which is the one to use for a button-triggered menu. " +
76
+ "Rendered open and inline in design mode.",
77
+
78
+ // ---- Navigation --------------------------------------------------------
79
+ Menubar:
80
+ "A persistent application menu bar (File / Edit / View). For a single button-triggered menu use `DropdownMenu`. " +
81
+ "Rendered open and inline in design mode.",
82
+ NavigationMenu:
83
+ "Site-level navigation with rich dropdown panels — marketing headers. " +
84
+ "For in-page section switching use `Tabs`.",
85
+
86
+ // ---- Chat & AI ---------------------------------------------------------
87
+ Bubble:
88
+ "One chat turn's speech bubble; `BubbleGroup` stacks consecutive turns from the same author " +
89
+ "and `BubbleReactions` adds the reaction row. For a full turn with avatar and header, use `Message`.",
90
+ Message:
91
+ "A full chat turn: `MessageAvatar` + `MessageHeader` + `MessageContent` (+ `MessageFooter`). " +
92
+ "`MessageGroup` wraps a transcript. Use `Bubble` when you only need the bubble itself.",
93
+ Attachment:
94
+ "A file chip attached to a chat message — `AttachmentMedia` + `AttachmentTitle`/`AttachmentDescription`, " +
95
+ "with `AttachmentGroup` for several and `AttachmentActions` for remove/download.",
96
+ Marker: "Inline annotation highlighting a span of chat text (citations, references).",
97
+ };
@@ -0,0 +1,47 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import pkg from "../package.json" with { type: "json" };
5
+
6
+ /** Date stamp recording which upstream shadcn pull this snapshot mirrors. */
7
+ export const snapshotVersion: string = (pkg as { snapshotVersion: string }).snapshotVersion;
8
+
9
+ const here = dirname(fileURLToPath(import.meta.url));
10
+
11
+ /**
12
+ * Package root holding `src/` (the component sources + Tailwind entry CSS) and
13
+ * `dist/manifest.json`. Resolves from source (`here` = this `src/` dir) and
14
+ * from the bundled CLI, where `build.ts` copies these assets to
15
+ * `<dist>/pkgs/shadcn-snapshot` next to `cli.js`.
16
+ */
17
+ function resolveRoot(): string {
18
+ const dev = join(here, "..");
19
+ const candidates = [
20
+ process.env.VELLOO_SNAPSHOT_ROOT,
21
+ join(here, "pkgs", "shadcn-snapshot"),
22
+ dev,
23
+ ].filter((p): p is string => Boolean(p));
24
+ return candidates.find((r) => existsSync(join(r, "src", "tailwind-entry.css"))) ?? dev;
25
+ }
26
+
27
+ const root = resolveRoot();
28
+ const srcDir = join(root, "src");
29
+ const distDir = join(root, "dist");
30
+
31
+ /**
32
+ * Absolute path to the Tailwind entry CSS shipped with the snapshot. The
33
+ * server's JIT compiler reads this and runs Tailwind v4 against the live
34
+ * page folder so any class — including ones we haven't thought of yet —
35
+ * renders without a hand-rolled safelist.
36
+ */
37
+ export const entryCssPath: string = join(srcDir, "tailwind-entry.css");
38
+
39
+ /**
40
+ * Absolute path to the snapshot's component sources. The JIT scanner reads
41
+ * these so the canvas picks up classes used by shipped components even if
42
+ * no page references them directly.
43
+ */
44
+ export const componentsDir: string = join(srcDir, "components");
45
+
46
+ /** Absolute path to the prebuilt manifest JSON (filled at `bun run build`). */
47
+ export const manifestPath: string = join(distDir, "manifest.json");