velloo 0.0.0 → 0.1.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 (262) hide show
  1. package/BUN-LICENSE.md +91 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +9 -0
  4. package/README.md +262 -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-BcBJ11d2.js +28 -0
  16. package/canvas/assets/lucide-all-BdEyryfF.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-0t68szgr.js +3 -0
  30. package/chunk-1bywxgc5.js +4 -0
  31. package/chunk-1gx45384.js +41 -0
  32. package/chunk-1y50g9vp.js +2 -0
  33. package/chunk-1yhc252b.js +3 -0
  34. package/chunk-2mv65qxs.js +5 -0
  35. package/chunk-2smsg2ct.js +7 -0
  36. package/chunk-2vx420g2.js +442 -0
  37. package/chunk-2z0k59hz.js +3 -0
  38. package/chunk-329e3phg.js +451 -0
  39. package/chunk-40657ggd.js +10 -0
  40. package/chunk-56vqqr8s.js +3 -0
  41. package/chunk-582y60bv.js +2 -0
  42. package/chunk-5js0qw32.js +2 -0
  43. package/chunk-5x173xay.js +2 -0
  44. package/chunk-65wb0g7d.js +3 -0
  45. package/chunk-6tx68d90.js +3 -0
  46. package/chunk-74skmg76.js +2 -0
  47. package/chunk-75wbh438.js +2 -0
  48. package/chunk-79ykzywe.js +4 -0
  49. package/chunk-7dggmqwq.js +53 -0
  50. package/chunk-7e39xe21.js +18 -0
  51. package/chunk-7p7ha0qk.js +3 -0
  52. package/chunk-8ssr8a8w.js +89 -0
  53. package/chunk-946pcnt5.js +5 -0
  54. package/chunk-9vg3yafz.js +3 -0
  55. package/chunk-aapybh30.js +6 -0
  56. package/chunk-b2ebm1t3.js +303 -0
  57. package/chunk-b7j86xq7.js +4 -0
  58. package/chunk-bjnhhsak.js +2 -0
  59. package/chunk-bk8b7f9a.js +62 -0
  60. package/chunk-cep3ktr3.js +4 -0
  61. package/chunk-cxe6jjwj.js +3 -0
  62. package/chunk-d385435m.js +8 -0
  63. package/chunk-dt03awr1.js +2 -0
  64. package/chunk-e2ag33vd.js +226 -0
  65. package/chunk-erwfk47h.js +3 -0
  66. package/chunk-fgw3hp2v.js +3 -0
  67. package/chunk-fjbzk4sw.js +3 -0
  68. package/chunk-g02nd9hn.js +4 -0
  69. package/chunk-h0c36khx.js +2 -0
  70. package/chunk-h6gchare.js +3 -0
  71. package/chunk-hggap8fq.js +3 -0
  72. package/chunk-hs2j6s1v.js +75 -0
  73. package/chunk-jnsfgtn9.js +3 -0
  74. package/chunk-jrsknzjt.js +3 -0
  75. package/chunk-k6ferbam.js +4 -0
  76. package/chunk-k784090q.js +6 -0
  77. package/chunk-kxk5x7g6.js +3 -0
  78. package/chunk-mq4znqv2.js +2 -0
  79. package/chunk-mzhdrawd.js +3 -0
  80. package/chunk-n5007jcz.js +2 -0
  81. package/chunk-nfr3q7mg.js +5 -0
  82. package/chunk-nsqs1bqf.js +2 -0
  83. package/chunk-nwx5700b.js +3 -0
  84. package/chunk-pphgrsxa.js +2 -0
  85. package/chunk-qpvj6kzq.js +6 -0
  86. package/chunk-qwv7xkms.js +2 -0
  87. package/chunk-rksq3w72.js +244 -0
  88. package/chunk-s23gtejf.js +3 -0
  89. package/chunk-t2ttkxe9.js +85 -0
  90. package/chunk-tmtzxcs5.js +2 -0
  91. package/chunk-vbk1qhdz.js +3 -0
  92. package/chunk-w5rzk6ms.js +1229 -0
  93. package/chunk-xr6f94rj.js +2 -0
  94. package/chunk-y0zxzefg.js +5 -0
  95. package/chunk-zf3xc1wz.js +2 -0
  96. package/cli.js +3 -0
  97. package/launcher.cjs +97 -0
  98. package/package.json +58 -5
  99. package/pkgs/helpers/src/box.tsx +21 -0
  100. package/pkgs/helpers/src/cn.ts +32 -0
  101. package/pkgs/helpers/src/descriptors.ts +270 -0
  102. package/pkgs/helpers/src/divider.tsx +123 -0
  103. package/pkgs/helpers/src/gradient.tsx +90 -0
  104. package/pkgs/helpers/src/heading.tsx +20 -0
  105. package/pkgs/helpers/src/icon-data.ts +8009 -0
  106. package/pkgs/helpers/src/icon.tsx +53 -0
  107. package/pkgs/helpers/src/image.tsx +111 -0
  108. package/pkgs/helpers/src/index.ts +29 -0
  109. package/pkgs/helpers/src/layer.tsx +61 -0
  110. package/pkgs/helpers/src/lowering.ts +53 -0
  111. package/pkgs/helpers/src/paths.ts +47 -0
  112. package/pkgs/helpers/src/placeholder.tsx +88 -0
  113. package/pkgs/helpers/src/prose.tsx +42 -0
  114. package/pkgs/helpers/src/registry.ts +41 -0
  115. package/pkgs/helpers/src/svg.tsx +62 -0
  116. package/pkgs/helpers/src/text.tsx +16 -0
  117. package/pkgs/provider-antd/src/index.ts +78 -0
  118. package/pkgs/provider-antd/src/intro.ts +14 -0
  119. package/pkgs/provider-antd/src/manifest.ts +439 -0
  120. package/pkgs/provider-antd/src/overlays.ts +176 -0
  121. package/pkgs/provider-antd/src/registry.ts +104 -0
  122. package/pkgs/provider-antd/src/render-pass.ts +43 -0
  123. package/pkgs/provider-antd/src/tailwind-entry.css +21 -0
  124. package/pkgs/provider-antd/src/theme.ts +132 -0
  125. package/pkgs/provider-antd/src/version.ts +8 -0
  126. package/pkgs/provider-chakra/src/index.ts +80 -0
  127. package/pkgs/provider-chakra/src/intro.ts +14 -0
  128. package/pkgs/provider-chakra/src/manifest.ts +421 -0
  129. package/pkgs/provider-chakra/src/overlays.ts +246 -0
  130. package/pkgs/provider-chakra/src/registry.ts +227 -0
  131. package/pkgs/provider-chakra/src/render-pass.ts +55 -0
  132. package/pkgs/provider-chakra/src/tailwind-entry.css +21 -0
  133. package/pkgs/provider-chakra/src/theme.ts +180 -0
  134. package/pkgs/provider-chakra/src/version.ts +8 -0
  135. package/pkgs/provider-mui/src/index.ts +117 -0
  136. package/pkgs/provider-mui/src/intro.ts +12 -0
  137. package/pkgs/provider-mui/src/manifest.ts +263 -0
  138. package/pkgs/provider-mui/src/overlays.ts +124 -0
  139. package/pkgs/provider-mui/src/registry.ts +120 -0
  140. package/pkgs/provider-mui/src/render-pass.ts +36 -0
  141. package/pkgs/provider-mui/src/tailwind-entry.css +21 -0
  142. package/pkgs/provider-mui/src/theme.ts +129 -0
  143. package/pkgs/provider-mui/src/version.ts +8 -0
  144. package/pkgs/provider-none/src/components-inline.tsx +204 -0
  145. package/pkgs/provider-none/src/components.tsx +155 -0
  146. package/pkgs/provider-none/src/index.ts +57 -0
  147. package/pkgs/provider-none/src/intro.ts +18 -0
  148. package/pkgs/provider-none/src/manifest.ts +163 -0
  149. package/pkgs/provider-none/src/registry-inline.ts +36 -0
  150. package/pkgs/provider-none/src/registry.ts +39 -0
  151. package/pkgs/provider-none/src/tailwind-entry.css +57 -0
  152. package/pkgs/provider-none/src/version.ts +10 -0
  153. package/pkgs/schema/src/annotation.ts +120 -0
  154. package/pkgs/schema/src/asset.ts +66 -0
  155. package/pkgs/schema/src/board.ts +71 -0
  156. package/pkgs/schema/src/comment.ts +107 -0
  157. package/pkgs/schema/src/config.ts +178 -0
  158. package/pkgs/schema/src/css-sanitize.ts +56 -0
  159. package/pkgs/schema/src/extension.ts +105 -0
  160. package/pkgs/schema/src/fonts.ts +690 -0
  161. package/pkgs/schema/src/frame.ts +40 -0
  162. package/pkgs/schema/src/icon-name.ts +21 -0
  163. package/pkgs/schema/src/ids.ts +14 -0
  164. package/pkgs/schema/src/index.ts +161 -0
  165. package/pkgs/schema/src/migrate.ts +244 -0
  166. package/pkgs/schema/src/node.ts +229 -0
  167. package/pkgs/schema/src/paths.ts +28 -0
  168. package/pkgs/schema/src/repo.ts +52 -0
  169. package/pkgs/schema/src/screen.ts +30 -0
  170. package/pkgs/schema/src/snippet-resolve.ts +193 -0
  171. package/pkgs/schema/src/snippet.ts +104 -0
  172. package/pkgs/schema/src/svg-sanitize.ts +74 -0
  173. package/pkgs/schema/src/theme.ts +218 -0
  174. package/pkgs/schema/src/typeset.ts +693 -0
  175. package/pkgs/schema/src/validate-ids.ts +46 -0
  176. package/pkgs/schema/src/viewport.ts +8 -0
  177. package/pkgs/shadcn-snapshot/dist/manifest.json +8109 -0
  178. package/pkgs/shadcn-snapshot/src/components/canvas-portal.tsx +55 -0
  179. package/pkgs/shadcn-snapshot/src/components/ui/accordion.tsx +122 -0
  180. package/pkgs/shadcn-snapshot/src/components/ui/alert-dialog.tsx +164 -0
  181. package/pkgs/shadcn-snapshot/src/components/ui/alert.tsx +74 -0
  182. package/pkgs/shadcn-snapshot/src/components/ui/aspect-ratio.tsx +13 -0
  183. package/pkgs/shadcn-snapshot/src/components/ui/attachment.tsx +197 -0
  184. package/pkgs/shadcn-snapshot/src/components/ui/avatar.tsx +100 -0
  185. package/pkgs/shadcn-snapshot/src/components/ui/badge.tsx +50 -0
  186. package/pkgs/shadcn-snapshot/src/components/ui/breadcrumb.tsx +109 -0
  187. package/pkgs/shadcn-snapshot/src/components/ui/bubble.tsx +130 -0
  188. package/pkgs/shadcn-snapshot/src/components/ui/button-group.tsx +82 -0
  189. package/pkgs/shadcn-snapshot/src/components/ui/button.tsx +72 -0
  190. package/pkgs/shadcn-snapshot/src/components/ui/calendar.tsx +229 -0
  191. package/pkgs/shadcn-snapshot/src/components/ui/card.tsx +92 -0
  192. package/pkgs/shadcn-snapshot/src/components/ui/carousel.tsx +235 -0
  193. package/pkgs/shadcn-snapshot/src/components/ui/chart-option.ts +250 -0
  194. package/pkgs/shadcn-snapshot/src/components/ui/chart.tsx +177 -0
  195. package/pkgs/shadcn-snapshot/src/components/ui/checkbox.tsx +41 -0
  196. package/pkgs/shadcn-snapshot/src/components/ui/collapsible.tsx +32 -0
  197. package/pkgs/shadcn-snapshot/src/components/ui/combobox.tsx +196 -0
  198. package/pkgs/shadcn-snapshot/src/components/ui/context-menu.tsx +227 -0
  199. package/pkgs/shadcn-snapshot/src/components/ui/dialog.tsx +131 -0
  200. package/pkgs/shadcn-snapshot/src/components/ui/direction.tsx +24 -0
  201. package/pkgs/shadcn-snapshot/src/components/ui/drawer.tsx +112 -0
  202. package/pkgs/shadcn-snapshot/src/components/ui/dropdown-menu.tsx +205 -0
  203. package/pkgs/shadcn-snapshot/src/components/ui/empty.tsx +98 -0
  204. package/pkgs/shadcn-snapshot/src/components/ui/field.tsx +228 -0
  205. package/pkgs/shadcn-snapshot/src/components/ui/hover-card.tsx +51 -0
  206. package/pkgs/shadcn-snapshot/src/components/ui/input-group.tsx +148 -0
  207. package/pkgs/shadcn-snapshot/src/components/ui/input.tsx +43 -0
  208. package/pkgs/shadcn-snapshot/src/components/ui/item.tsx +187 -0
  209. package/pkgs/shadcn-snapshot/src/components/ui/kbd.tsx +30 -0
  210. package/pkgs/shadcn-snapshot/src/components/ui/label.tsx +25 -0
  211. package/pkgs/shadcn-snapshot/src/components/ui/marker.tsx +71 -0
  212. package/pkgs/shadcn-snapshot/src/components/ui/menubar.tsx +243 -0
  213. package/pkgs/shadcn-snapshot/src/components/ui/message.tsx +89 -0
  214. package/pkgs/shadcn-snapshot/src/components/ui/native-select.tsx +60 -0
  215. package/pkgs/shadcn-snapshot/src/components/ui/navigation-menu.tsx +165 -0
  216. package/pkgs/shadcn-snapshot/src/components/ui/pagination.tsx +117 -0
  217. package/pkgs/shadcn-snapshot/src/components/ui/popover.tsx +66 -0
  218. package/pkgs/shadcn-snapshot/src/components/ui/progress.tsx +35 -0
  219. package/pkgs/shadcn-snapshot/src/components/ui/radio-group.tsx +48 -0
  220. package/pkgs/shadcn-snapshot/src/components/ui/scroll-area.tsx +59 -0
  221. package/pkgs/shadcn-snapshot/src/components/ui/select.tsx +180 -0
  222. package/pkgs/shadcn-snapshot/src/components/ui/separator.tsx +32 -0
  223. package/pkgs/shadcn-snapshot/src/components/ui/sheet.tsx +107 -0
  224. package/pkgs/shadcn-snapshot/src/components/ui/skeleton.tsx +17 -0
  225. package/pkgs/shadcn-snapshot/src/components/ui/slider.tsx +68 -0
  226. package/pkgs/shadcn-snapshot/src/components/ui/sonner.tsx +91 -0
  227. package/pkgs/shadcn-snapshot/src/components/ui/spinner.tsx +21 -0
  228. package/pkgs/shadcn-snapshot/src/components/ui/switch.tsx +41 -0
  229. package/pkgs/shadcn-snapshot/src/components/ui/table.tsx +93 -0
  230. package/pkgs/shadcn-snapshot/src/components/ui/tabs.tsx +84 -0
  231. package/pkgs/shadcn-snapshot/src/components/ui/textarea.tsx +24 -0
  232. package/pkgs/shadcn-snapshot/src/components/ui/toggle-group.tsx +94 -0
  233. package/pkgs/shadcn-snapshot/src/components/ui/toggle.tsx +50 -0
  234. package/pkgs/shadcn-snapshot/src/components/ui/tooltip.tsx +47 -0
  235. package/pkgs/shadcn-snapshot/src/examples.ts +36 -0
  236. package/pkgs/shadcn-snapshot/src/groups.ts +87 -0
  237. package/pkgs/shadcn-snapshot/src/index.ts +43 -0
  238. package/pkgs/shadcn-snapshot/src/lib/utils.ts +4 -0
  239. package/pkgs/shadcn-snapshot/src/manifest.ts +12 -0
  240. package/pkgs/shadcn-snapshot/src/notes.ts +97 -0
  241. package/pkgs/shadcn-snapshot/src/paths.ts +47 -0
  242. package/pkgs/shadcn-snapshot/src/registry-files.ts +293 -0
  243. package/pkgs/shadcn-snapshot/src/registry.ts +631 -0
  244. package/pkgs/shadcn-snapshot/src/shadcn-tailwind.css +632 -0
  245. package/pkgs/shadcn-snapshot/src/tailwind-entry.css +159 -0
  246. package/pkgs/shadcn-snapshot/src/version.ts +8 -0
  247. package/plugins/claude/velloo/.claude-plugin/plugin.json +6 -0
  248. package/plugins/claude/velloo/agents/velloo-design-reviewer.md +33 -0
  249. package/plugins/claude/velloo/agents/velloo-designer.md +39 -0
  250. package/plugins/claude/velloo/commands/design.md +11 -0
  251. package/plugins/claude/velloo/commands/implement.md +10 -0
  252. package/plugins/claude/velloo/commands/review.md +8 -0
  253. package/plugins/gemini/GEMINI.md +31 -0
  254. package/plugins/gemini/commands/velloo/design.toml +10 -0
  255. package/plugins/gemini/commands/velloo/implement.toml +9 -0
  256. package/plugins/gemini/gemini-extension.json +9 -0
  257. package/skills/velloo-brand/SKILL.md +124 -0
  258. package/skills/velloo-design/SKILL.md +144 -0
  259. package/skills/velloo-design-system/SKILL.md +90 -0
  260. package/skills/velloo-implement/SKILL.md +101 -0
  261. package/skills/velloo-logo/SKILL.md +93 -0
  262. package/skills/velloo-setup/SKILL.md +156 -0
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{headingInlineStyle,textInlineStyle}from"./chunk-bk8b7f9a.js";import{clsx,helperDescriptors,require_react_jsx_dev_runtime_development,helpersRegistry,TAILWIND_CLASSNAME}from"./chunk-329e3phg.js";import{resolveProviderSrcDir}from"./chunk-fjbzk4sw.js";import{require_react_development}from"./chunk-w5rzk6ms.js";import{__toESM}from"./chunk-2smsg2ct.js";import{noLibVersion}from"./chunk-cxe6jjwj.js";import{dirname,join}from"path";import{fileURLToPath}from"url";var NONE_INTRO=["**This folder has no component library** \u2014 only bare primitives wrapping plain HTML: `Box`/`Stack`/`Container` for layout, `Card`, `Button`, `Input`, plus the velloo helpers (`Heading`/`Text`, `Image`, `Gradient`, `Layer`, `SVG`, `Divider`, `Placeholder`, `Icon`). There is no `Badge`/`Avatar`/`Tabs`/`Dialog` \u2014 build those from primitives or define snippets. Call `list_components` for the exact set. Styling is **Tailwind classes**.",""],NONE_INLINE_INTRO=["**This folder has no component library and no CSS framework** \u2014 bare primitives wrapping plain HTML (`Box`/`Stack`/`Container`, `Card`, `Button`, `Input`) plus the velloo helpers (`Heading`/`Text`, `Image`, `Icon`, `SVG`, `Divider`, `Gradient`, `Layer`, `Placeholder`). There is no `Badge`/`Avatar`/`Tabs`/`Dialog` \u2014 build those from primitives or snippets. Call `list_components` for the exact set.","",'**Style through inline `style` objects.** `update_props { style: { display: "flex", gap: "16px", padding: "24px", borderRadius: "8px", color: "var(--color-foreground)" } }` \u2014 a plain React style object (merges shallowly; an inner `null` drops a key, `style: null` clears). Reference theme tokens as CSS variables (`var(--color-primary)`, `var(--radius)`) from `get_theme` so the design stays themable. `emit_code` emits `style={{\u2026}}` on plain elements \u2014 no imports, no Tailwind. Tailwind utility diagnostics do not apply.',""];var React=__toESM(require_react_development(),1),jsx_dev_runtime=__toESM(require_react_jsx_dev_runtime_development(),1),Box=React.forwardRef(({className,...rest},ref)=>jsx_dev_runtime.jsxDEV("div",{ref,className:clsx(className),...rest},void 0,!1,void 0,this));Box.displayName="Box";var alignClass={start:"items-start",center:"items-center",end:"items-end",stretch:"items-stretch"},justifyClass={start:"justify-start",center:"justify-center",end:"justify-end",between:"justify-between",around:"justify-around"},Stack=React.forwardRef(({direction="col",gap=4,align,justify,className,...rest},ref)=>jsx_dev_runtime.jsxDEV("div",{ref,className:clsx("flex",direction==="row"?"flex-row":"flex-col",`gap-${gap}`,align?alignClass[align]:void 0,justify?justifyClass[justify]:void 0,className),...rest},void 0,!1,void 0,this));Stack.displayName="Stack";var containerWidth={sm:"max-w-screen-sm",md:"max-w-screen-md",lg:"max-w-screen-lg",xl:"max-w-screen-xl",full:"max-w-full"},Container=React.forwardRef(({size="md",className,...rest},ref)=>jsx_dev_runtime.jsxDEV("div",{ref,className:clsx("mx-auto w-full px-4",containerWidth[size],className),...rest},void 0,!1,void 0,this));Container.displayName="Container";var buttonVariant={default:"bg-foreground text-background hover:bg-foreground/90",ghost:"bg-transparent text-foreground hover:bg-muted",outline:"bg-transparent text-foreground border border-border hover:bg-muted"},Button=React.forwardRef(({variant="default",className,type,...rest},ref)=>jsx_dev_runtime.jsxDEV("button",{ref,type:type??"button",className:clsx("inline-flex items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium","focus-visible:outline-2 focus-visible:outline-offset-2",buttonVariant[variant],className),...rest},void 0,!1,void 0,this));Button.displayName="Button";var Input=React.forwardRef(({className,type="text",value,onChange,...rest},ref)=>jsx_dev_runtime.jsxDEV("input",{ref,type,value,onChange,readOnly:value!==void 0&&onChange===void 0||rest.readOnly,className:clsx("block w-full rounded-md border border-input bg-background px-3 py-2 text-sm","placeholder:text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-2",className),...rest},void 0,!1,void 0,this));Input.displayName="Input";var Card=React.forwardRef(({className,...rest},ref)=>jsx_dev_runtime.jsxDEV("div",{ref,className:clsx("rounded-lg border border-border bg-card p-6 text-card-foreground shadow-sm",className),...rest},void 0,!1,void 0,this));Card.displayName="Card";var REUSED_HELPER_IDS=["Heading","Text","Prose","Icon","SVG","Image","Layer","Divider","Gradient","Placeholder"],registry={Box,Stack,Container,Card,Button,Input,...helpersRegistry(REUSED_HELPER_IDS)};var PRIMITIVE_DESCRIPTORS=[{id:"Box",category:"ui",source:"velloo",props:[{name:"className",type:"string | undefined",optional:!0,control:"string"}]},{id:"Stack",category:"ui",source:"velloo",props:[{name:"direction",type:'"row" | "col" | undefined',optional:!0,control:"enum",enumValues:["row","col"],defaultValue:"col"},{name:"gap",type:"number | undefined",optional:!0,control:"number",defaultValue:"4"},{name:"align",type:'"start" | "center" | "end" | "stretch" | undefined',optional:!0,control:"enum",enumValues:["start","center","end","stretch"]},{name:"justify",type:'"start" | "center" | "end" | "between" | "around" | undefined',optional:!0,control:"enum",enumValues:["start","center","end","between","around"]},{name:"className",type:"string | undefined",optional:!0,control:"string"}]},{id:"Container",category:"ui",source:"velloo",props:[{name:"size",type:'"sm" | "md" | "lg" | "xl" | "full" | undefined',optional:!0,control:"enum",enumValues:["sm","md","lg","xl","full"],defaultValue:"md"},{name:"className",type:"string | undefined",optional:!0,control:"string"}]},{id:"Card",category:"ui",source:"velloo",props:[{name:"className",type:"string | undefined",optional:!0,control:"string"}]},{id:"Button",category:"ui",source:"velloo",props:[{name:"variant",type:'"default" | "ghost" | "outline" | undefined',optional:!0,control:"enum",enumValues:["default","ghost","outline"],defaultValue:"default"},{name:"className",type:"string | undefined",optional:!0,control:"string"}]},{id:"Input",category:"ui",source:"velloo",props:[{name:"placeholder",type:"string | undefined",optional:!0,control:"string"},{name:"value",type:"string | undefined",optional:!0,control:"string"},{name:"type",type:"string | undefined",optional:!0,control:"string",defaultValue:"text"},{name:"className",type:"string | undefined",optional:!0,control:"string"}]}],NONE_MANIFEST=[...PRIMITIVE_DESCRIPTORS,...helperDescriptors(REUSED_HELPER_IDS)];var React2=__toESM(require_react_development(),1),jsx_dev_runtime2=__toESM(require_react_jsx_dev_runtime_development(),1);function merge(defaults,authored){return authored?{...defaults,...authored}:defaults}var space=(n)=>`${n*0.25}rem`,Box2=React2.forwardRef(({style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("div",{ref,style,...rest},void 0,!1,void 0,this));Box2.displayName="Box";var alignStyle={start:"flex-start",center:"center",end:"flex-end",stretch:"stretch"},justifyStyle={start:"flex-start",center:"center",end:"flex-end",between:"space-between",around:"space-around"},Stack2=React2.forwardRef(({direction="col",gap=4,align,justify,style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("div",{ref,style:merge({display:"flex",flexDirection:direction==="row"?"row":"column",gap:space(gap),...align?{alignItems:alignStyle[align]}:{},...justify?{justifyContent:justifyStyle[justify]}:{}},style),...rest},void 0,!1,void 0,this));Stack2.displayName="Stack";var containerMaxWidth={sm:"640px",md:"768px",lg:"1024px",xl:"1280px",full:"100%"},Container2=React2.forwardRef(({size="md",style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("div",{ref,style:merge({marginInline:"auto",width:"100%",paddingInline:"1rem",maxWidth:containerMaxWidth[size]},style),...rest},void 0,!1,void 0,this));Container2.displayName="Container";var buttonVariantStyle={default:{background:"var(--color-foreground)",color:"var(--color-background)"},ghost:{background:"transparent",color:"var(--color-foreground)"},outline:{background:"transparent",color:"var(--color-foreground)",border:"1px solid var(--color-border)"}},Button2=React2.forwardRef(({variant="default",type,style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("button",{ref,type:type??"button",style:merge({display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"0.5rem",borderRadius:"var(--radius)",padding:"0.5rem 1rem",fontSize:"0.875rem",fontWeight:500,cursor:"pointer",...buttonVariantStyle[variant]},style),...rest},void 0,!1,void 0,this));Button2.displayName="Button";var Input2=React2.forwardRef(({type="text",value,onChange,style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("input",{ref,type,value,onChange,readOnly:value!==void 0&&onChange===void 0||rest.readOnly,style:merge({display:"block",width:"100%",borderRadius:"var(--radius)",border:"1px solid var(--color-input)",background:"var(--color-background)",padding:"0.5rem 0.75rem",fontSize:"0.875rem"},style),...rest},void 0,!1,void 0,this));Input2.displayName="Input";var Card2=React2.forwardRef(({style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("div",{ref,style:merge({borderRadius:"var(--radius)",border:"1px solid var(--color-border)",background:"var(--color-card)",color:"var(--color-card-foreground)",padding:"1.5rem",boxShadow:"0 1px 2px 0 rgb(0 0 0 / 0.05)"},style),...rest},void 0,!1,void 0,this));Card2.displayName="Card";var Heading=React2.forwardRef(({level=1,style,...rest},ref)=>{let Tag=`h${level}`;return jsx_dev_runtime2.jsxDEV(Tag,{ref,style:merge(headingInlineStyle(level),style),...rest},void 0,!1,void 0,this)});Heading.displayName="Heading";var Text=React2.forwardRef(({variant="default",style,...rest},ref)=>jsx_dev_runtime2.jsxDEV("p",{ref,style:merge(textInlineStyle(variant),style),...rest},void 0,!1,void 0,this));Text.displayName="Text";var REUSED_HELPER_IDS2=["Prose","Icon","SVG","Image","Layer","Divider","Gradient","Placeholder"],inlineRegistry={Box:Box2,Stack:Stack2,Container:Container2,Card:Card2,Button:Button2,Input:Input2,Heading,Text,...helpersRegistry(REUSED_HELPER_IDS2)};var here=dirname(fileURLToPath(import.meta.url)),srcDir=resolveProviderSrcDir(here,"provider-none",process.env.VELLOO_NOLIB_SRC),entryCssPath=join(srcDir,"tailwind-entry.css"),componentsDir=srcDir;async function loadManifest(){return NONE_MANIFEST}function createProvider(){return{id:"none",version:noLibVersion,componentsDir,styleEntryPath:entryCssPath,registry,loadManifest,label:`none ${noLibVersion}`,styleChannel:TAILWIND_CLASSNAME,styleChannels:["tailwind-classname","style"],mcpIntro:(channel)=>[...channel==="style"?NONE_INLINE_INTRO:NONE_INTRO],registryForChannel:(kind)=>kind==="style"?inlineRegistry:registry}}export{createProvider};
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ import{CURRENT_SCHEMA_VERSION,schemaVersionOf,planMigration}from"./chunk-bk8b7f9a.js";import{loadDesignFolder}from"./chunk-329e3phg.js";import{TOOL_VERSION}from"./chunk-65wb0g7d.js";import{readdir,readFile,writeFile}from"fs/promises";import{join}from"path";function isObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}var isAnnotationSidecar=(file)=>file.endsWith(".annotations.json"),isThemeDocument=(file)=>file.endsWith(".json");async function planRewrites(folder,dir,matches,transform){let files=[];try{files=await readdir(join(folder,dir))}catch{return[]}let out=[];for(let file of files.sort()){if(!matches(file))continue;let rel=join(dir,file),prev=await readFile(join(folder,rel),"utf8"),next=`${JSON.stringify(transform(JSON.parse(prev)),null,2)}
3
+ `;if(next!==prev)out.push({rel,next})}return out}async function upgradeFolder(folder,opts={}){let configPath=join(folder,".design","config.json"),rawConfig=JSON.parse(await readFile(configPath,"utf8")),from=schemaVersionOf(rawConfig),run=planMigration(rawConfig);if(run.applied.length===0)return{from,to:CURRENT_SCHEMA_VERSION,applied:[],changedFiles:[]};let rewrites=[...await planRewrites(folder,"screens",isAnnotationSidecar,(parsed)=>Array.isArray(parsed)?parsed.map((e)=>typeof e==="object"&&e!==null?run.annotation(e):e):parsed),...await planRewrites(folder,"theme",isThemeDocument,(parsed)=>isObject(parsed)?run.theme(parsed):parsed)],nextConfig={...run.config,toolVersion:TOOL_VERSION},changedFiles=[join(".design","config.json"),...rewrites.map((r)=>r.rel)];if(opts.dryRun)return{from,to:CURRENT_SCHEMA_VERSION,applied:run.applied,changedFiles};await writeFile(configPath,`${JSON.stringify(nextConfig,null,2)}
4
+ `,"utf8");for(let r of rewrites)await writeFile(join(folder,r.rel),r.next,"utf8");return await loadDesignFolder(folder),{from,to:CURRENT_SCHEMA_VERSION,applied:run.applied,changedFiles}}
5
+ export{upgradeFolder};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import"./chunk-mq4znqv2.js";import"./chunk-bk8b7f9a.js";import{loadCredential}from"./chunk-b7j86xq7.js";import"./chunk-329e3phg.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{listDaemons}from"./chunk-k784090q.js";import{verifyCredential}from"./chunk-fgw3hp2v.js";import{projectLabel}from"./chunk-1bywxgc5.js";import{defaultCloudUrl}from"./chunk-2z0k59hz.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var status_default=defineCommand({meta:{name:"status",description:"List the velloo canvas daemons running on this machine + cloud sign-in"},args:{},async run(){let daemons=await listDaemons();if(daemons.length===0)console.log("velloo: no canvas daemons running.");else for(let d of daemons){let label=await projectLabel(d.root)??d.root;console.log(`${d.canvasUrl} ${label} (pid ${d.pid}, since ${d.startedAt})`)}let cloudUrl=defaultCloudUrl(),cred=await loadCredential(cloudUrl);if(!cred){console.log(import_picocolors.default.dim(`cloud: not signed in (${cloudUrl}) \u2014 run \`velloo login\` to share.`));return}let email=await verifyCredential(cloudUrl,cred.token,3000);console.log(email?`cloud: signed in as ${email} (${cloudUrl})`:import_picocolors.default.dim(`cloud: stored credential for ${cred.email} (${cloudUrl}) \u2014 expired or cloud unreachable; \`velloo login\` to refresh.`))}});export{status_default as default};
package/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ import"./chunk-s23gtejf.js";import{COMMANDS}from"./chunk-1yhc252b.js";import{TOOL_VERSION}from"./chunk-65wb0g7d.js";import{maybeNotifyAboutUpdate}from"./chunk-cep3ktr3.js";import{defineCommand,runMain}from"./chunk-2smsg2ct.js";var main=defineCommand({meta:{name:"velloo",version:TOOL_VERSION,description:"Local, agent-driven canvas for redesigning an existing React screen against the running app, then sharing the result with a team or external reviewer."},subCommands:COMMANDS});await runMain(main);var command=process.argv[2];if(!["mcp","__daemon","__update_check","run","upgrade"].includes(command??""))await maybeNotifyAboutUpdate();
package/launcher.cjs ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { existsSync, readFileSync } = require("node:fs");
5
+ const { dirname, join } = require("node:path");
6
+ const { spawnSync } = require("node:child_process");
7
+
8
+ function linuxLibc() {
9
+ if (process.platform !== "linux") return undefined;
10
+ try {
11
+ const report = process.report?.getReport();
12
+ if (report?.header?.glibcVersionRuntime) return "glibc";
13
+ } catch {}
14
+ try {
15
+ if (/musl/i.test(readFileSync("/usr/bin/ldd", "utf8"))) return "musl";
16
+ } catch {}
17
+ return "musl";
18
+ }
19
+
20
+ function runtimePackage() {
21
+ const arch = process.arch === "x64" ? "x64" : process.arch === "arm64" ? "arm64" : null;
22
+ if (!arch) return null;
23
+ if (process.platform === "darwin") {
24
+ return arch === "arm64" ? "@oven/bun-darwin-aarch64" : "@oven/bun-darwin-x64-baseline";
25
+ }
26
+ if (process.platform === "win32") {
27
+ return arch === "arm64" ? "@oven/bun-windows-aarch64" : "@oven/bun-windows-x64-baseline";
28
+ }
29
+ if (process.platform === "linux") {
30
+ const musl = linuxLibc() === "musl";
31
+ if (arch === "arm64") {
32
+ return musl ? "@oven/bun-linux-aarch64-musl" : "@oven/bun-linux-aarch64";
33
+ }
34
+ return musl ? "@oven/bun-linux-x64-musl-baseline" : "@oven/bun-linux-x64-baseline";
35
+ }
36
+ return null;
37
+ }
38
+
39
+ function die(message) {
40
+ process.stderr.write(`velloo: ${message}\n`);
41
+ process.exit(1);
42
+ }
43
+
44
+ // Windows cannot reliably replace an executable while that executable is
45
+ // running. Handle the bare self-upgrade in the Node launcher before Bun starts;
46
+ // folder migrations and `--check` still go through the normal CLI command.
47
+ if (process.platform === "win32" && process.argv.length === 3 && process.argv[2] === "upgrade") {
48
+ const adjacentNpm = join(dirname(process.execPath), "npm.cmd");
49
+ const npm = existsSync(adjacentNpm) ? adjacentNpm : "npm.cmd";
50
+ const packageName = process.env.VELLOO_NPM_PACKAGE || "velloo";
51
+ const upgrade = spawnSync(npm, ["install", "-g", `${packageName}@latest`], { stdio: "inherit" });
52
+ if (upgrade.error) die(`could not start npm: ${upgrade.error.message}`);
53
+ if (upgrade.status !== 0) process.exit(upgrade.status == null ? 1 : upgrade.status);
54
+ // npm rewrote this launcher's package in place, so re-entering by the same
55
+ // path runs the NEW velloo — which is the one that must migrate the design
56
+ // folder, since only it knows the format it migrated towards.
57
+ const migrate = spawnSync(process.execPath, [__filename, "upgrade", "--folder-only"], {
58
+ stdio: "inherit",
59
+ });
60
+ process.exit(migrate.status == null ? 1 : migrate.status);
61
+ }
62
+
63
+ const runtimeName = runtimePackage();
64
+ if (!runtimeName) {
65
+ die(
66
+ `unsupported platform ${process.platform}/${process.arch}; supported platforms are macOS, Linux, and Windows on x64 or arm64`,
67
+ );
68
+ }
69
+
70
+ let runtimeRoot;
71
+ try {
72
+ runtimeRoot = dirname(require.resolve(`${runtimeName}/package.json`));
73
+ } catch {
74
+ die(
75
+ `the Bun runtime package ${runtimeName} is missing. Reinstall with \`npm install -g velloo@latest\` and make sure optional dependencies are enabled`,
76
+ );
77
+ }
78
+
79
+ const runtime = join(runtimeRoot, "bin", process.platform === "win32" ? "bun.exe" : "bun");
80
+ if (!existsSync(runtime)) die(`the Bun runtime package ${runtimeName} is incomplete`);
81
+
82
+ const app = join(__dirname, "cli.js");
83
+ const child = spawnSync(runtime, [app, ...process.argv.slice(2)], {
84
+ stdio: "inherit",
85
+ env: {
86
+ ...process.env,
87
+ VELLOO_INSTALL_METHOD: process.env.VELLOO_INSTALL_METHOD || "npm",
88
+ VELLOO_NPM_PACKAGE: process.env.VELLOO_NPM_PACKAGE || "velloo",
89
+ VELLOO_NODE_EXECUTABLE: process.execPath,
90
+ // The install path is how a Homebrew-managed velloo is told apart from an
91
+ // npm one under a Homebrew-installed Node (both live under /opt/homebrew).
92
+ VELLOO_LAUNCHER_PATH: __filename,
93
+ },
94
+ });
95
+
96
+ if (child.error) die(`could not start the bundled Bun runtime: ${child.error.message}`);
97
+ process.exit(child.status == null ? 1 : child.status);
package/package.json CHANGED
@@ -1,11 +1,64 @@
1
1
  {
2
2
  "name": "velloo",
3
- "version": "0.0.0",
4
- "description": "Reserved.",
5
- "license": "UNLICENSED",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Local-first, code-shaped design canvas — your AI agent designs with your real components, in your repo",
6
+ "license": "Apache-2.0",
7
+ "homepage": "https://github.com/velloo-design/velloo#readme",
6
8
  "repository": {
7
9
  "type": "git",
8
- "url": "git+https://github.com/velloo-dev/velloo.git"
10
+ "url": "git+https://github.com/velloo-design/velloo.git"
9
11
  },
10
- "homepage": "https://velloo.dev"
12
+ "bugs": {
13
+ "url": "https://github.com/velloo-design/velloo/issues"
14
+ },
15
+ "keywords": [
16
+ "design",
17
+ "design-tool",
18
+ "canvas",
19
+ "mcp",
20
+ "ai-agent",
21
+ "claude-code",
22
+ "shadcn",
23
+ "tailwind",
24
+ "mui",
25
+ "local-first",
26
+ "bun"
27
+ ],
28
+ "bin": {
29
+ "velloo": "./launcher.cjs"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "files": [
35
+ "cli.js",
36
+ "launcher.cjs",
37
+ "chunk-*.js",
38
+ "assets",
39
+ "canvas",
40
+ "skills",
41
+ "plugins",
42
+ "pkgs",
43
+ "NOTICE",
44
+ "THIRD-PARTY-NOTICES.md",
45
+ "BUN-LICENSE.md"
46
+ ],
47
+ "dependencies": {
48
+ "@tailwindcss/node": "4.3.3",
49
+ "@tailwindcss/oxide": "4.3.3",
50
+ "playwright-core": "1.62.1",
51
+ "tailwindcss": "4.3.3",
52
+ "tw-animate-css": "1.4.0"
53
+ },
54
+ "optionalDependencies": {
55
+ "@oven/bun-darwin-aarch64": "1.4.2",
56
+ "@oven/bun-darwin-x64-baseline": "1.4.2",
57
+ "@oven/bun-linux-aarch64": "1.4.2",
58
+ "@oven/bun-linux-aarch64-musl": "1.4.2",
59
+ "@oven/bun-linux-x64-baseline": "1.4.2",
60
+ "@oven/bun-linux-x64-musl-baseline": "1.4.2",
61
+ "@oven/bun-windows-aarch64": "1.4.2",
62
+ "@oven/bun-windows-x64-baseline": "1.4.2"
63
+ }
11
64
  }
@@ -0,0 +1,21 @@
1
+ // Velloo-owned generic container. Designs are mostly layout: before Box
2
+ // existed every flex/grid wrapper was a Card with its chrome reset
3
+ // ("ring-0 shadow-none bg-transparent rounded-none p-0"), which bloated
4
+ // trees and invited styling accidents (Card's overflow-hidden clipping
5
+ // children). Box is a plain div: no chrome, no padding, no surprises —
6
+ // className is the whole API. Codegen lowers it to `<as ?? div>`.
7
+
8
+ import type * as React from "react";
9
+ import { createElement } from "react";
10
+ import { cn } from "./cn.ts";
11
+
12
+ // Restrict `as` to a lowercase HTML tag name. Anything else (a component
13
+ // reference, an injection attempt) falls back to div. Rendering the real tag
14
+ // means inline elements (span/strong/a/…) get their natural inline display
15
+ // from the UA stylesheet, instead of a div's block stacking inline runs.
16
+ const TAG = /^[a-z][a-z0-9]*$/;
17
+
18
+ export function Box({ as, className, ...props }: React.ComponentProps<"div"> & { as?: string }) {
19
+ const tag = typeof as === "string" && TAG.test(as) ? as : "div";
20
+ return createElement(tag, { "data-slot": "box", className: cn(className), ...props });
21
+ }
@@ -0,0 +1,32 @@
1
+ import { TYPESET_SCALE_NAMES } from "@velloo/schema/typeset";
2
+ import { type ClassValue, clsx } from "clsx";
3
+ import { extendTailwindMerge } from "tailwind-merge";
4
+
5
+ /**
6
+ * The typeset ladder's utilities are theme-generated, so stock tailwind-merge
7
+ * has never heard of them: it would classify `text-h1` as a *color* (the
8
+ * `text-<color>` group) and `leading-h1` / `tracking-h1` as unknown. That
9
+ * misfiling both kept a component default alive next to an author's override
10
+ * (`<Heading className="text-sm">` still carried `text-h1`, and the larger one
11
+ * won) and dropped a size next to a tone (`text-body text-foreground`).
12
+ *
13
+ * Registering the role names in the right groups restores last-wins per group,
14
+ * which every helper relies on for `className` to be an override.
15
+ *
16
+ * Exported as the ONE merge for velloo-owned class strings — codegen's emit and
17
+ * the snapshot runtime use it too, so a typeset class survives the same way in
18
+ * the canvas and in generated code.
19
+ */
20
+ export const mergeTailwind = extendTailwindMerge({
21
+ extend: {
22
+ classGroups: {
23
+ "font-size": TYPESET_SCALE_NAMES.map((role) => `text-${role}`),
24
+ leading: TYPESET_SCALE_NAMES.map((role) => `leading-${role}`),
25
+ tracking: TYPESET_SCALE_NAMES.map((role) => `tracking-${role}`),
26
+ },
27
+ },
28
+ });
29
+
30
+ export function cn(...inputs: ClassValue[]): string {
31
+ return mergeTailwind(clsx(inputs));
32
+ }
@@ -0,0 +1,270 @@
1
+ import type { ComponentDescriptor } from "@velloo/provider";
2
+
3
+ /**
4
+ * The canonical manifest entries for the velloo helpers (`source: "velloo"`).
5
+ * Single source: the shadcn snapshot's `build.ts` splices these into its
6
+ * generated `dist/manifest.json` (augmenting `Icon.name` with the live
7
+ * lucide-react name list at build time), and `provider-none` composes its
8
+ * hand-authored manifest from them. Keep each entry mirroring the co-located
9
+ * component's props (`./heading.tsx`, `./icon.tsx`, …).
10
+ */
11
+ export const HELPER_DESCRIPTORS: readonly ComponentDescriptor[] = [
12
+ {
13
+ id: "Box",
14
+ category: "ui",
15
+ group: "layout",
16
+ family: "Box",
17
+ source: "velloo",
18
+ props: [],
19
+ example: { className: "flex flex-col gap-6 px-8 py-12" },
20
+ },
21
+ {
22
+ id: "Divider",
23
+ category: "ui",
24
+ group: "layout",
25
+ family: "Divider",
26
+ source: "velloo",
27
+ props: [
28
+ {
29
+ name: "variant",
30
+ type: '"solid" | "dotted" | "dashed" | "gradient" | "pinched" | undefined',
31
+ optional: true,
32
+ control: "enum",
33
+ enumValues: ["solid", "dotted", "dashed", "gradient", "pinched"],
34
+ },
35
+ {
36
+ name: "orientation",
37
+ type: '"horizontal" | "vertical" | undefined',
38
+ optional: true,
39
+ control: "enum",
40
+ enumValues: ["horizontal", "vertical"],
41
+ },
42
+ { name: "label", type: "string | undefined", optional: true, control: "string" },
43
+ {
44
+ name: "color",
45
+ type: '"primary" | "accent" | "muted" | "border" | undefined',
46
+ optional: true,
47
+ control: "enum",
48
+ enumValues: ["primary", "accent", "muted", "border"],
49
+ },
50
+ ],
51
+ example: { variant: "gradient", color: "primary", label: "OR" },
52
+ },
53
+ {
54
+ id: "Gradient",
55
+ category: "ui",
56
+ group: "visuals",
57
+ family: "Gradient",
58
+ source: "velloo",
59
+ props: [
60
+ {
61
+ name: "preset",
62
+ type: '"primary" | "accent" | "radial" | "mesh" | "dusk" | "dawn" | undefined',
63
+ optional: true,
64
+ control: "enum",
65
+ enumValues: ["primary", "accent", "radial", "mesh", "dusk", "dawn"],
66
+ },
67
+ {
68
+ name: "direction",
69
+ type: '"t" | "b" | "l" | "r" | "tl" | "tr" | "bl" | "br" | undefined',
70
+ optional: true,
71
+ control: "enum",
72
+ enumValues: ["t", "b", "l", "r", "tl", "tr", "bl", "br"],
73
+ },
74
+ ],
75
+ example: {
76
+ preset: "dusk",
77
+ direction: "br",
78
+ className: "absolute inset-0 -z-0 pointer-events-none",
79
+ },
80
+ },
81
+ {
82
+ id: "Heading",
83
+ category: "typography",
84
+ group: "typography",
85
+ family: "Heading",
86
+ source: "velloo",
87
+ props: [
88
+ {
89
+ name: "level",
90
+ type: "1 | 2 | 3 | 4 | 5 | 6 | undefined",
91
+ optional: true,
92
+ control: "enum",
93
+ enumValues: [1, 2, 3, 4, 5, 6],
94
+ },
95
+ ],
96
+ example: { level: 2, children: "Section title", className: "text-3xl font-semibold" },
97
+ },
98
+ {
99
+ id: "Icon",
100
+ category: "ui",
101
+ group: "visuals",
102
+ family: "Icon",
103
+ source: "velloo",
104
+ props: [
105
+ // `enumValues` (the lucide icon name list) is injected at snapshot build
106
+ // time from the installed lucide-react, so it never drifts from what the
107
+ // Icon component can actually resolve.
108
+ { name: "name", type: "string", optional: false, control: "icon", defaultValue: "Heart" },
109
+ { name: "size", type: "number | undefined", optional: true, control: "number" },
110
+ { name: "strokeWidth", type: "number | undefined", optional: true, control: "number" },
111
+ ],
112
+ designModeNotes:
113
+ "`name` accepts any lucide-react icon, PascalCase (ArrowRight) or kebab-case (arrow-right); full list at lucide.dev (the enumValues here are sampled). " +
114
+ "`size` sets width/height in px, but a Tailwind sizing class in `className` (e.g. `size-4`) wins via CSS — pass one or the other, not both expecting `size` to apply.",
115
+ example: { name: "Sparkles", className: "size-4 text-primary" },
116
+ },
117
+ {
118
+ id: "Image",
119
+ category: "ui",
120
+ group: "visuals",
121
+ family: "Image",
122
+ source: "velloo",
123
+ props: [
124
+ { name: "src", type: "string", optional: false, control: "string" },
125
+ {
126
+ name: "aspect",
127
+ type: '"1/1" | "4/3" | "3/4" | "16/9" | "21/9" | undefined',
128
+ optional: true,
129
+ control: "enum",
130
+ enumValues: ["1/1", "4/3", "3/4", "16/9", "21/9"],
131
+ },
132
+ {
133
+ name: "focal",
134
+ type: "{ x: number; y: number; } | undefined",
135
+ optional: true,
136
+ control: "string",
137
+ },
138
+ {
139
+ name: "treatment",
140
+ type: '"overlay-dark" | "overlay-light" | "blend-multiply" | "grayscale" | undefined',
141
+ optional: true,
142
+ control: "enum",
143
+ enumValues: ["overlay-dark", "overlay-light", "blend-multiply", "grayscale"],
144
+ },
145
+ { name: "fill", type: "boolean | undefined", optional: true, control: "boolean" },
146
+ ],
147
+ example: {
148
+ src: "/assets/hero.png",
149
+ aspect: "16/9",
150
+ focal: { x: 0.5, y: 0.35 },
151
+ treatment: "overlay-dark",
152
+ className: "rounded-xl",
153
+ },
154
+ },
155
+ {
156
+ id: "Layer",
157
+ category: "ui",
158
+ group: "layout",
159
+ family: "Layer",
160
+ source: "velloo",
161
+ props: [
162
+ { name: "top", type: "string | number | undefined", optional: true, control: "string" },
163
+ { name: "right", type: "string | number | undefined", optional: true, control: "string" },
164
+ { name: "bottom", type: "string | number | undefined", optional: true, control: "string" },
165
+ { name: "left", type: "string | number | undefined", optional: true, control: "string" },
166
+ { name: "z", type: "number | undefined", optional: true, control: "number" },
167
+ { name: "pointerEvents", type: "boolean | undefined", optional: true, control: "boolean" },
168
+ ],
169
+ example: { top: 16, left: 16, z: 2 },
170
+ },
171
+ {
172
+ id: "Placeholder",
173
+ category: "ui",
174
+ group: "visuals",
175
+ family: "Placeholder",
176
+ source: "velloo",
177
+ props: [
178
+ {
179
+ name: "kind",
180
+ type: '"image" | "avatar" | undefined',
181
+ optional: true,
182
+ control: "enum",
183
+ enumValues: ["image", "avatar"],
184
+ },
185
+ { name: "label", type: "string | undefined", optional: true, control: "string" },
186
+ {
187
+ name: "aspect",
188
+ type: '"1/1" | "4/3" | "3/4" | "16/9" | "21/9" | undefined',
189
+ optional: true,
190
+ control: "enum",
191
+ enumValues: ["1/1", "4/3", "3/4", "16/9", "21/9"],
192
+ },
193
+ {
194
+ name: "size",
195
+ type: '"sm" | "lg" | "md" | "xl" | undefined',
196
+ optional: true,
197
+ control: "enum",
198
+ enumValues: ["sm", "lg", "md", "xl"],
199
+ },
200
+ ],
201
+ example: { kind: "image", aspect: "16/9", label: "product screenshot" },
202
+ },
203
+ {
204
+ id: "Prose",
205
+ category: "typography",
206
+ group: "typography",
207
+ family: "Prose",
208
+ source: "velloo",
209
+ props: [
210
+ {
211
+ name: "preset",
212
+ type: "string | undefined",
213
+ optional: true,
214
+ control: "string",
215
+ },
216
+ { name: "as", type: "string | undefined", optional: true, control: "string" },
217
+ ],
218
+ example: { as: "article", className: "max-w-prose" },
219
+ },
220
+ {
221
+ id: "SVG",
222
+ category: "ui",
223
+ group: "visuals",
224
+ family: "SVG",
225
+ source: "velloo",
226
+ props: [
227
+ { name: "content", type: "string | undefined", optional: true, control: "string" },
228
+ { name: "viewBox", type: "string | undefined", optional: true, control: "string" },
229
+ { name: "color", type: "string | undefined", optional: true, control: "color" },
230
+ ],
231
+ example: {
232
+ content: "<path d='M12 2 2 7l10 5 10-5-10-5z' />",
233
+ viewBox: "0 0 24 24",
234
+ color: "primary",
235
+ className: "h-8 w-8",
236
+ },
237
+ },
238
+ {
239
+ id: "Text",
240
+ category: "typography",
241
+ group: "typography",
242
+ family: "Text",
243
+ source: "velloo",
244
+ props: [
245
+ {
246
+ name: "variant",
247
+ type: '"muted" | "default" | "small" | "lead" | undefined',
248
+ optional: true,
249
+ control: "enum",
250
+ enumValues: ["muted", "default", "small", "lead"],
251
+ },
252
+ ],
253
+ example: { variant: "muted", children: "Supporting copy." },
254
+ },
255
+ ];
256
+
257
+ /**
258
+ * Subset selector mirroring `helpersRegistry` — each provider passes its own
259
+ * deliberate id list and gets the canonical descriptors in that order.
260
+ * Unknown ids are skipped.
261
+ */
262
+ export function helperDescriptors(ids: readonly string[]): ComponentDescriptor[] {
263
+ const byId = new Map(HELPER_DESCRIPTORS.map((d) => [d.id, d]));
264
+ const out: ComponentDescriptor[] = [];
265
+ for (const id of ids) {
266
+ const descriptor = byId.get(id);
267
+ if (descriptor) out.push(descriptor);
268
+ }
269
+ return out;
270
+ }
@@ -0,0 +1,123 @@
1
+ // Velloo-owned decorative divider. shadcn's Separator is a single
2
+ // border-bg-border rule — fine for app chrome but too plain for
3
+ // marketing pages. Divider adds variant styles (dotted, gradient,
4
+ // pinched) and a label slot for "OR" / "section break" usage.
5
+ import type * as React from "react";
6
+ import { cn } from "./cn.ts";
7
+
8
+ export interface DividerProps extends React.HTMLAttributes<HTMLDivElement> {
9
+ variant?: "solid" | "dotted" | "dashed" | "gradient" | "pinched";
10
+ orientation?: "horizontal" | "vertical";
11
+ /** Optional centered label, like "OR" or "section break". */
12
+ label?: string;
13
+ /** Color source — semantic token name; defaults to border. */
14
+ color?: "border" | "muted" | "primary" | "accent";
15
+ }
16
+
17
+ const COLOR_BORDER: Record<NonNullable<DividerProps["color"]>, string> = {
18
+ border: "border-border",
19
+ muted: "border-muted-foreground/30",
20
+ primary: "border-primary/40",
21
+ accent: "border-accent/60",
22
+ };
23
+
24
+ const COLOR_BG: Record<NonNullable<DividerProps["color"]>, string> = {
25
+ border: "from-border via-border to-border",
26
+ muted: "from-transparent via-muted-foreground/40 to-transparent",
27
+ primary: "from-transparent via-primary to-transparent",
28
+ accent: "from-transparent via-accent to-transparent",
29
+ };
30
+
31
+ const VARIANT_BORDER: Record<NonNullable<DividerProps["variant"]>, string> = {
32
+ solid: "border-solid",
33
+ dotted: "border-dotted",
34
+ dashed: "border-dashed",
35
+ gradient: "",
36
+ pinched: "border-solid",
37
+ };
38
+
39
+ export function Divider({
40
+ variant = "solid",
41
+ orientation = "horizontal",
42
+ label,
43
+ color = "border",
44
+ className,
45
+ ...rest
46
+ }: DividerProps) {
47
+ if (label) {
48
+ return (
49
+ <div
50
+ data-slot="divider"
51
+ data-variant={variant}
52
+ className={cn(
53
+ "flex items-center gap-3 text-xs uppercase tracking-wider text-muted-foreground",
54
+ className,
55
+ )}
56
+ {...rest}
57
+ >
58
+ <span
59
+ className={cn(
60
+ "flex-1",
61
+ variant === "gradient"
62
+ ? cn("h-px bg-gradient-to-r", COLOR_BG[color])
63
+ : cn("border-t", VARIANT_BORDER[variant], COLOR_BORDER[color]),
64
+ )}
65
+ />
66
+ <span className="shrink-0">{label}</span>
67
+ <span
68
+ className={cn(
69
+ "flex-1",
70
+ variant === "gradient"
71
+ ? cn("h-px bg-gradient-to-r", COLOR_BG[color])
72
+ : cn("border-t", VARIANT_BORDER[variant], COLOR_BORDER[color]),
73
+ )}
74
+ />
75
+ </div>
76
+ );
77
+ }
78
+
79
+ if (variant === "gradient") {
80
+ return (
81
+ <div
82
+ data-slot="divider"
83
+ data-variant="gradient"
84
+ className={cn(
85
+ orientation === "horizontal" ? "h-px w-full" : "w-px self-stretch",
86
+ "bg-gradient-to-r",
87
+ COLOR_BG[color],
88
+ className,
89
+ )}
90
+ {...rest}
91
+ />
92
+ );
93
+ }
94
+
95
+ if (variant === "pinched") {
96
+ return (
97
+ <div
98
+ data-slot="divider"
99
+ data-variant="pinched"
100
+ className={cn("flex items-center justify-center w-full", className)}
101
+ {...rest}
102
+ >
103
+ <span className={cn("h-px w-16 border-t", COLOR_BORDER[color])} />
104
+ <span className={cn("mx-1 size-1.5 rounded-full", COLOR_BG[color].split(" ")[1] ?? "")} />
105
+ <span className={cn("h-px w-16 border-t", COLOR_BORDER[color])} />
106
+ </div>
107
+ );
108
+ }
109
+
110
+ return (
111
+ <div
112
+ data-slot="divider"
113
+ data-variant={variant}
114
+ className={cn(
115
+ orientation === "horizontal"
116
+ ? cn("w-full border-t", VARIANT_BORDER[variant], COLOR_BORDER[color])
117
+ : cn("self-stretch border-l", VARIANT_BORDER[variant], COLOR_BORDER[color]),
118
+ className,
119
+ )}
120
+ {...rest}
121
+ />
122
+ );
123
+ }