@slexn/codecenter-ui 1.0.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 (472) hide show
  1. package/LICENSE +34 -0
  2. package/README.md +148 -0
  3. package/components.json +20 -0
  4. package/dist/codecenter-ui.cjs +10 -0
  5. package/dist/codecenter-ui.js +17995 -0
  6. package/dist/components/ui/accordion/Accordion.vue.d.ts +28 -0
  7. package/dist/components/ui/accordion/AccordionContent.vue.d.ts +22 -0
  8. package/dist/components/ui/accordion/AccordionItem.vue.d.ts +24 -0
  9. package/dist/components/ui/accordion/AccordionTrigger.vue.d.ts +22 -0
  10. package/dist/components/ui/accordion/index.d.ts +4 -0
  11. package/dist/components/ui/alert/Alert.vue.d.ts +32 -0
  12. package/dist/components/ui/alert/AlertDescription.vue.d.ts +24 -0
  13. package/dist/components/ui/alert/AlertTitle.vue.d.ts +24 -0
  14. package/dist/components/ui/alert/index.d.ts +4 -0
  15. package/dist/components/ui/alert/variants.d.ts +5 -0
  16. package/dist/components/ui/button/Button.vue.d.ts +27 -0
  17. package/dist/components/ui/button/index.d.ts +2 -0
  18. package/dist/components/ui/button/variants.d.ts +6 -0
  19. package/dist/components/ui/button-group/ButtonGroup.vue.d.ts +25 -0
  20. package/dist/components/ui/button-group/index.d.ts +2 -0
  21. package/dist/components/ui/card/Card.vue.d.ts +21 -0
  22. package/dist/components/ui/card/CardContent.vue.d.ts +21 -0
  23. package/dist/components/ui/card/CardDescription.vue.d.ts +21 -0
  24. package/dist/components/ui/card/CardFooter.vue.d.ts +21 -0
  25. package/dist/components/ui/card/CardHeader.vue.d.ts +21 -0
  26. package/dist/components/ui/card/CardTitle.vue.d.ts +21 -0
  27. package/dist/components/ui/card/index.d.ts +6 -0
  28. package/dist/components/ui/chart/Chart.vue.d.ts +92 -0
  29. package/dist/components/ui/chart/index.d.ts +2 -0
  30. package/dist/components/ui/chat/Chat.vue.d.ts +190 -0
  31. package/dist/components/ui/chat/ChatAttachments.vue.d.ts +11 -0
  32. package/dist/components/ui/chat/ChatCodeBlock.vue.d.ts +16 -0
  33. package/dist/components/ui/chat/code-block.d.ts +27 -0
  34. package/dist/components/ui/chat/index.d.ts +6 -0
  35. package/dist/components/ui/chat/types.d.ts +15 -0
  36. package/dist/components/ui/checkbox/Checkbox.vue.d.ts +29 -0
  37. package/dist/components/ui/checkbox/index.d.ts +1 -0
  38. package/dist/components/ui/commit/Commit.vue.d.ts +62 -0
  39. package/dist/components/ui/commit/index.d.ts +2 -0
  40. package/dist/components/ui/contribution-graph/ContributionGraph.vue.d.ts +87 -0
  41. package/dist/components/ui/contribution-graph/index.d.ts +2 -0
  42. package/dist/components/ui/data-table/DataTable.vue.d.ts +109 -0
  43. package/dist/components/ui/data-table/index.d.ts +2 -0
  44. package/dist/components/ui/date-picker/DatePicker.vue.d.ts +37 -0
  45. package/dist/components/ui/date-picker/index.d.ts +2 -0
  46. package/dist/components/ui/dialog/Dialog.vue.d.ts +25 -0
  47. package/dist/components/ui/dialog/DialogClose.vue.d.ts +18 -0
  48. package/dist/components/ui/dialog/DialogContent.vue.d.ts +39 -0
  49. package/dist/components/ui/dialog/DialogDescription.vue.d.ts +22 -0
  50. package/dist/components/ui/dialog/DialogFooter.vue.d.ts +21 -0
  51. package/dist/components/ui/dialog/DialogHeader.vue.d.ts +21 -0
  52. package/dist/components/ui/dialog/DialogOverlay.vue.d.ts +22 -0
  53. package/dist/components/ui/dialog/DialogScrollContent.vue.d.ts +36 -0
  54. package/dist/components/ui/dialog/DialogTitle.vue.d.ts +22 -0
  55. package/dist/components/ui/dialog/DialogTrigger.vue.d.ts +18 -0
  56. package/dist/components/ui/dialog/index.d.ts +10 -0
  57. package/dist/components/ui/diff/DiffTool.vue.d.ts +21 -0
  58. package/dist/components/ui/diff/diff-parser.d.ts +30 -0
  59. package/dist/components/ui/diff/diff-tool.d.ts +36 -0
  60. package/dist/components/ui/diff/index.d.ts +2 -0
  61. package/dist/components/ui/dropdown-menu/DropdownMenu.vue.d.ts +24 -0
  62. package/dist/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue.d.ts +29 -0
  63. package/dist/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +36 -0
  64. package/dist/components/ui/dropdown-menu/DropdownMenuGroup.vue.d.ts +18 -0
  65. package/dist/components/ui/dropdown-menu/DropdownMenuItem.vue.d.ts +26 -0
  66. package/dist/components/ui/dropdown-menu/DropdownMenuLabel.vue.d.ts +23 -0
  67. package/dist/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue.d.ts +22 -0
  68. package/dist/components/ui/dropdown-menu/DropdownMenuRadioItem.vue.d.ts +27 -0
  69. package/dist/components/ui/dropdown-menu/DropdownMenuSeparator.vue.d.ts +7 -0
  70. package/dist/components/ui/dropdown-menu/DropdownMenuShortcut.vue.d.ts +21 -0
  71. package/dist/components/ui/dropdown-menu/DropdownMenuSub.vue.d.ts +22 -0
  72. package/dist/components/ui/dropdown-menu/DropdownMenuSubContent.vue.d.ts +38 -0
  73. package/dist/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue.d.ts +23 -0
  74. package/dist/components/ui/dropdown-menu/DropdownMenuTrigger.vue.d.ts +18 -0
  75. package/dist/components/ui/dropdown-menu/index.d.ts +15 -0
  76. package/dist/components/ui/gauge/Gauge.vue.d.ts +62 -0
  77. package/dist/components/ui/gauge/index.d.ts +2 -0
  78. package/dist/components/ui/git-graph/GitGraph.vue.d.ts +59 -0
  79. package/dist/components/ui/git-graph/index.d.ts +2 -0
  80. package/dist/components/ui/incident-timeline/IncidentTimeline.vue.d.ts +50 -0
  81. package/dist/components/ui/incident-timeline/index.d.ts +2 -0
  82. package/dist/components/ui/input/Input.vue.d.ts +14 -0
  83. package/dist/components/ui/input/InputControl.vue.d.ts +14 -0
  84. package/dist/components/ui/input/InputFieldGroup.vue.d.ts +21 -0
  85. package/dist/components/ui/input/index.d.ts +4 -0
  86. package/dist/components/ui/input/types.d.ts +31 -0
  87. package/dist/components/ui/kpi-card/KpiCard.vue.d.ts +46 -0
  88. package/dist/components/ui/kpi-card/index.d.ts +2 -0
  89. package/dist/components/ui/kpi-line-card/KpiLineCard.vue.d.ts +66 -0
  90. package/dist/components/ui/kpi-line-card/index.d.ts +2 -0
  91. package/dist/components/ui/model-selector/ModelSelector.vue.d.ts +41 -0
  92. package/dist/components/ui/model-selector/index.d.ts +2 -0
  93. package/dist/components/ui/model-selector/types.d.ts +12 -0
  94. package/dist/components/ui/network-graph/NetworkGraph.vue.d.ts +75 -0
  95. package/dist/components/ui/network-graph/index.d.ts +2 -0
  96. package/dist/components/ui/pagination/Pagination.vue.d.ts +29 -0
  97. package/dist/components/ui/pagination/PaginationContent.vue.d.ts +29 -0
  98. package/dist/components/ui/pagination/PaginationEllipsis.vue.d.ts +22 -0
  99. package/dist/components/ui/pagination/PaginationFirst.vue.d.ts +26 -0
  100. package/dist/components/ui/pagination/PaginationItem.vue.d.ts +28 -0
  101. package/dist/components/ui/pagination/PaginationLast.vue.d.ts +26 -0
  102. package/dist/components/ui/pagination/PaginationNext.vue.d.ts +26 -0
  103. package/dist/components/ui/pagination/PaginationPrevious.vue.d.ts +26 -0
  104. package/dist/components/ui/pagination/index.d.ts +8 -0
  105. package/dist/components/ui/profile/Profile.vue.d.ts +30 -0
  106. package/dist/components/ui/profile/ProfileGroup.vue.d.ts +37 -0
  107. package/dist/components/ui/profile/index.d.ts +4 -0
  108. package/dist/components/ui/progress/Progress.vue.d.ts +36 -0
  109. package/dist/components/ui/progress/index.d.ts +2 -0
  110. package/dist/components/ui/prompt-input/PromptInput.vue.d.ts +150 -0
  111. package/dist/components/ui/prompt-input/index.d.ts +2 -0
  112. package/dist/components/ui/prompt-input/types.d.ts +61 -0
  113. package/dist/components/ui/radio-group/RadioGroup.vue.d.ts +30 -0
  114. package/dist/components/ui/radio-group/RadioGroupItem.vue.d.ts +12 -0
  115. package/dist/components/ui/radio-group/RadioGroupOption.vue.d.ts +28 -0
  116. package/dist/components/ui/radio-group/index.d.ts +3 -0
  117. package/dist/components/ui/reasoning/Reasoning.vue.d.ts +40 -0
  118. package/dist/components/ui/reasoning/index.d.ts +2 -0
  119. package/dist/components/ui/reasoning/types.d.ts +26 -0
  120. package/dist/components/ui/select/Select.vue.d.ts +28 -0
  121. package/dist/components/ui/select/SelectContent.vue.d.ts +46 -0
  122. package/dist/components/ui/select/SelectGroup.vue.d.ts +18 -0
  123. package/dist/components/ui/select/SelectItem.vue.d.ts +26 -0
  124. package/dist/components/ui/select/SelectItemText.vue.d.ts +18 -0
  125. package/dist/components/ui/select/SelectLabel.vue.d.ts +22 -0
  126. package/dist/components/ui/select/SelectScrollDownButton.vue.d.ts +22 -0
  127. package/dist/components/ui/select/SelectScrollUpButton.vue.d.ts +22 -0
  128. package/dist/components/ui/select/SelectSeparator.vue.d.ts +7 -0
  129. package/dist/components/ui/select/SelectTrigger.vue.d.ts +25 -0
  130. package/dist/components/ui/select/SelectValue.vue.d.ts +18 -0
  131. package/dist/components/ui/select/index.d.ts +11 -0
  132. package/dist/components/ui/select/search.d.ts +18 -0
  133. package/dist/components/ui/separator/Separator.vue.d.ts +6 -0
  134. package/dist/components/ui/separator/index.d.ts +2 -0
  135. package/dist/components/ui/separator/types.d.ts +7 -0
  136. package/dist/components/ui/shimmer/Shimmer.vue.d.ts +37 -0
  137. package/dist/components/ui/shimmer/index.d.ts +2 -0
  138. package/dist/components/ui/sidebar/Sidebar.vue.d.ts +24 -0
  139. package/dist/components/ui/sidebar/SidebarContent.vue.d.ts +21 -0
  140. package/dist/components/ui/sidebar/SidebarFooter.vue.d.ts +21 -0
  141. package/dist/components/ui/sidebar/SidebarGroup.vue.d.ts +21 -0
  142. package/dist/components/ui/sidebar/SidebarGroupAction.vue.d.ts +24 -0
  143. package/dist/components/ui/sidebar/SidebarGroupContent.vue.d.ts +21 -0
  144. package/dist/components/ui/sidebar/SidebarGroupLabel.vue.d.ts +24 -0
  145. package/dist/components/ui/sidebar/SidebarHeader.vue.d.ts +21 -0
  146. package/dist/components/ui/sidebar/SidebarInput.vue.d.ts +6 -0
  147. package/dist/components/ui/sidebar/SidebarInset.vue.d.ts +21 -0
  148. package/dist/components/ui/sidebar/SidebarMenu.vue.d.ts +21 -0
  149. package/dist/components/ui/sidebar/SidebarMenuAction.vue.d.ts +25 -0
  150. package/dist/components/ui/sidebar/SidebarMenuBadge.vue.d.ts +21 -0
  151. package/dist/components/ui/sidebar/SidebarMenuButton.vue.d.ts +25 -0
  152. package/dist/components/ui/sidebar/SidebarMenuButtonChild.vue.d.ts +30 -0
  153. package/dist/components/ui/sidebar/SidebarMenuItem.vue.d.ts +21 -0
  154. package/dist/components/ui/sidebar/SidebarMenuSub.vue.d.ts +21 -0
  155. package/dist/components/ui/sidebar/SidebarMenuSubButton.vue.d.ts +27 -0
  156. package/dist/components/ui/sidebar/SidebarMenuSubItem.vue.d.ts +21 -0
  157. package/dist/components/ui/sidebar/SidebarProvider.vue.d.ts +36 -0
  158. package/dist/components/ui/sidebar/SidebarRail.vue.d.ts +21 -0
  159. package/dist/components/ui/sidebar/SidebarSeparator.vue.d.ts +6 -0
  160. package/dist/components/ui/sidebar/SidebarTrigger.vue.d.ts +6 -0
  161. package/dist/components/ui/sidebar/context.d.ts +19 -0
  162. package/dist/components/ui/sidebar/index.d.ts +26 -0
  163. package/dist/components/ui/sidebar/types.d.ts +11 -0
  164. package/dist/components/ui/sidebar/variants.d.ts +6 -0
  165. package/dist/components/ui/skeleton/Skeleton.vue.d.ts +18 -0
  166. package/dist/components/ui/skeleton/index.d.ts +2 -0
  167. package/dist/components/ui/sonner/Sonner.vue.d.ts +5 -0
  168. package/dist/components/ui/sonner/index.d.ts +2 -0
  169. package/dist/components/ui/spinner/Spinner.vue.d.ts +11 -0
  170. package/dist/components/ui/spinner/index.d.ts +1 -0
  171. package/dist/components/ui/stepper/Stepper.vue.d.ts +38 -0
  172. package/dist/components/ui/stepper/StepperDescription.vue.d.ts +22 -0
  173. package/dist/components/ui/stepper/StepperIndicator.vue.d.ts +30 -0
  174. package/dist/components/ui/stepper/StepperItem.vue.d.ts +24 -0
  175. package/dist/components/ui/stepper/StepperSeparator.vue.d.ts +7 -0
  176. package/dist/components/ui/stepper/StepperTitle.vue.d.ts +22 -0
  177. package/dist/components/ui/stepper/StepperTrigger.vue.d.ts +22 -0
  178. package/dist/components/ui/stepper/index.d.ts +7 -0
  179. package/dist/components/ui/switch/Switch.vue.d.ts +12 -0
  180. package/dist/components/ui/switch/index.d.ts +1 -0
  181. package/dist/components/ui/table/Table.vue.d.ts +22 -0
  182. package/dist/components/ui/table/TableBody.vue.d.ts +21 -0
  183. package/dist/components/ui/table/TableCaption.vue.d.ts +21 -0
  184. package/dist/components/ui/table/TableCell.vue.d.ts +22 -0
  185. package/dist/components/ui/table/TableEmpty.vue.d.ts +24 -0
  186. package/dist/components/ui/table/TableFooter.vue.d.ts +21 -0
  187. package/dist/components/ui/table/TableHead.vue.d.ts +21 -0
  188. package/dist/components/ui/table/TableHeader.vue.d.ts +21 -0
  189. package/dist/components/ui/table/TableRow.vue.d.ts +21 -0
  190. package/dist/components/ui/table/index.d.ts +9 -0
  191. package/dist/components/ui/tabs/Tabs.vue.d.ts +28 -0
  192. package/dist/components/ui/tabs/TabsContent.vue.d.ts +22 -0
  193. package/dist/components/ui/tabs/TabsList.vue.d.ts +22 -0
  194. package/dist/components/ui/tabs/TabsTrigger.vue.d.ts +22 -0
  195. package/dist/components/ui/tabs/index.d.ts +4 -0
  196. package/dist/components/ui/tag/Tag.vue.d.ts +35 -0
  197. package/dist/components/ui/tag/index.d.ts +2 -0
  198. package/dist/components/ui/tag/variants.d.ts +6 -0
  199. package/dist/components/ui/textarea/Textarea.vue.d.ts +14 -0
  200. package/dist/components/ui/textarea/TextareaControl.vue.d.ts +14 -0
  201. package/dist/components/ui/textarea/TextareaFieldGroup.vue.d.ts +21 -0
  202. package/dist/components/ui/textarea/index.d.ts +4 -0
  203. package/dist/components/ui/textarea/types.d.ts +32 -0
  204. package/dist/components/ui/tool/Tool.vue.d.ts +61 -0
  205. package/dist/components/ui/tool/index.d.ts +2 -0
  206. package/dist/components/ui/tooltip/Tooltip.vue.d.ts +24 -0
  207. package/dist/components/ui/tooltip/TooltipContent.vue.d.ts +32 -0
  208. package/dist/components/ui/tooltip/TooltipProvider.vue.d.ts +20 -0
  209. package/dist/components/ui/tooltip/TooltipTrigger.vue.d.ts +18 -0
  210. package/dist/components/ui/tooltip/index.d.ts +4 -0
  211. package/dist/docs/component-docs.d.ts +18 -0
  212. package/dist/docs/markdown.d.ts +27 -0
  213. package/dist/index.d.ts +45 -0
  214. package/dist/lib/code-highlight.d.ts +11 -0
  215. package/dist/lib/utils.d.ts +2 -0
  216. package/dist/styles.css +3 -0
  217. package/package.json +76 -0
  218. package/public/r/accordion.json +52 -0
  219. package/public/r/alert.json +51 -0
  220. package/public/r/button-group.json +31 -0
  221. package/public/r/button.json +39 -0
  222. package/public/r/card.json +61 -0
  223. package/public/r/chart.json +31 -0
  224. package/public/r/chat.json +186 -0
  225. package/public/r/checkbox.json +34 -0
  226. package/public/r/commit.json +32 -0
  227. package/public/r/contribution-graph.json +63 -0
  228. package/public/r/data-table.json +197 -0
  229. package/public/r/date-picker.json +33 -0
  230. package/public/r/dialog.json +88 -0
  231. package/public/r/diff.json +71 -0
  232. package/public/r/dropdown-menu.json +112 -0
  233. package/public/r/gauge.json +31 -0
  234. package/public/r/git-graph.json +32 -0
  235. package/public/r/incident-timeline.json +64 -0
  236. package/public/r/input.json +49 -0
  237. package/public/r/kpi-card.json +32 -0
  238. package/public/r/kpi-line-card.json +32 -0
  239. package/public/r/model-selector.json +148 -0
  240. package/public/r/network-graph.json +33 -0
  241. package/public/r/pagination.json +95 -0
  242. package/public/r/profile.json +37 -0
  243. package/public/r/progress.json +31 -0
  244. package/public/r/prompt-input.json +293 -0
  245. package/public/r/radio-group.json +45 -0
  246. package/public/r/reasoning.json +38 -0
  247. package/public/r/registry.json +2512 -0
  248. package/public/r/select.json +100 -0
  249. package/public/r/separator.json +37 -0
  250. package/public/r/shimmer.json +31 -0
  251. package/public/r/sidebar.json +221 -0
  252. package/public/r/skeleton.json +31 -0
  253. package/public/r/sonner.json +33 -0
  254. package/public/r/spinner.json +31 -0
  255. package/public/r/stepper.json +70 -0
  256. package/public/r/switch.json +33 -0
  257. package/public/r/table.json +79 -0
  258. package/public/r/tabs.json +51 -0
  259. package/public/r/tag.json +39 -0
  260. package/public/r/textarea.json +49 -0
  261. package/public/r/tool.json +32 -0
  262. package/public/r/tooltip.json +51 -0
  263. package/registry.json +2512 -0
  264. package/src/components/docs/MarkdownContent.vue +106 -0
  265. package/src/components/ui/accordion/Accordion.vue +24 -0
  266. package/src/components/ui/accordion/AccordionContent.vue +62 -0
  267. package/src/components/ui/accordion/AccordionItem.vue +23 -0
  268. package/src/components/ui/accordion/AccordionTrigger.vue +38 -0
  269. package/src/components/ui/accordion/index.ts +4 -0
  270. package/src/components/ui/alert/Alert.vue +40 -0
  271. package/src/components/ui/alert/AlertDescription.vue +24 -0
  272. package/src/components/ui/alert/AlertTitle.vue +24 -0
  273. package/src/components/ui/alert/index.ts +4 -0
  274. package/src/components/ui/alert/variants.ts +19 -0
  275. package/src/components/ui/button/Button.vue +27 -0
  276. package/src/components/ui/button/index.ts +2 -0
  277. package/src/components/ui/button/variants.ts +32 -0
  278. package/src/components/ui/button-group/ButtonGroup.vue +31 -0
  279. package/src/components/ui/button-group/index.ts +2 -0
  280. package/src/components/ui/card/Card.vue +17 -0
  281. package/src/components/ui/card/CardContent.vue +14 -0
  282. package/src/components/ui/card/CardDescription.vue +14 -0
  283. package/src/components/ui/card/CardFooter.vue +14 -0
  284. package/src/components/ui/card/CardHeader.vue +17 -0
  285. package/src/components/ui/card/CardTitle.vue +14 -0
  286. package/src/components/ui/card/index.ts +6 -0
  287. package/src/components/ui/chart/Chart.vue +1042 -0
  288. package/src/components/ui/chart/index.ts +13 -0
  289. package/src/components/ui/chat/Chat.vue +1297 -0
  290. package/src/components/ui/chat/ChatAttachments.vue +278 -0
  291. package/src/components/ui/chat/ChatCodeBlock.vue +283 -0
  292. package/src/components/ui/chat/code-block.ts +30 -0
  293. package/src/components/ui/chat/index.ts +24 -0
  294. package/src/components/ui/chat/types.ts +23 -0
  295. package/src/components/ui/checkbox/Checkbox.vue +38 -0
  296. package/src/components/ui/checkbox/index.ts +1 -0
  297. package/src/components/ui/commit/Commit.vue +423 -0
  298. package/src/components/ui/commit/index.ts +9 -0
  299. package/src/components/ui/contribution-graph/ContributionGraph.vue +719 -0
  300. package/src/components/ui/contribution-graph/index.ts +9 -0
  301. package/src/components/ui/data-table/DataTable.vue +534 -0
  302. package/src/components/ui/data-table/index.ts +9 -0
  303. package/src/components/ui/date-picker/DatePicker.vue +649 -0
  304. package/src/components/ui/date-picker/index.ts +7 -0
  305. package/src/components/ui/dialog/Dialog.vue +19 -0
  306. package/src/components/ui/dialog/DialogClose.vue +17 -0
  307. package/src/components/ui/dialog/DialogContent.vue +60 -0
  308. package/src/components/ui/dialog/DialogDescription.vue +23 -0
  309. package/src/components/ui/dialog/DialogFooter.vue +17 -0
  310. package/src/components/ui/dialog/DialogHeader.vue +17 -0
  311. package/src/components/ui/dialog/DialogOverlay.vue +23 -0
  312. package/src/components/ui/dialog/DialogScrollContent.vue +69 -0
  313. package/src/components/ui/dialog/DialogTitle.vue +23 -0
  314. package/src/components/ui/dialog/DialogTrigger.vue +17 -0
  315. package/src/components/ui/dialog/index.ts +10 -0
  316. package/src/components/ui/diff/DiffTool.vue +513 -0
  317. package/src/components/ui/diff/diff-parser.ts +423 -0
  318. package/src/components/ui/diff/diff-tool.ts +39 -0
  319. package/src/components/ui/diff/index.ts +5 -0
  320. package/src/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
  321. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  322. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  323. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  324. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  325. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  326. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  327. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  328. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  329. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  330. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  331. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  332. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  333. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  334. package/src/components/ui/dropdown-menu/index.ts +16 -0
  335. package/src/components/ui/gauge/Gauge.vue +725 -0
  336. package/src/components/ui/gauge/index.ts +9 -0
  337. package/src/components/ui/git-graph/GitGraph.vue +715 -0
  338. package/src/components/ui/git-graph/index.ts +9 -0
  339. package/src/components/ui/incident-timeline/IncidentTimeline.vue +360 -0
  340. package/src/components/ui/incident-timeline/index.ts +7 -0
  341. package/src/components/ui/input/Input.vue +159 -0
  342. package/src/components/ui/input/InputControl.vue +135 -0
  343. package/src/components/ui/input/InputFieldGroup.vue +14 -0
  344. package/src/components/ui/input/index.ts +9 -0
  345. package/src/components/ui/input/types.ts +34 -0
  346. package/src/components/ui/kpi-card/KpiCard.vue +268 -0
  347. package/src/components/ui/kpi-card/index.ts +9 -0
  348. package/src/components/ui/kpi-line-card/KpiLineCard.vue +622 -0
  349. package/src/components/ui/kpi-line-card/index.ts +11 -0
  350. package/src/components/ui/model-selector/ModelSelector.vue +328 -0
  351. package/src/components/ui/model-selector/index.ts +6 -0
  352. package/src/components/ui/model-selector/types.ts +15 -0
  353. package/src/components/ui/network-graph/NetworkGraph.vue +902 -0
  354. package/src/components/ui/network-graph/index.ts +7 -0
  355. package/src/components/ui/pagination/Pagination.vue +26 -0
  356. package/src/components/ui/pagination/PaginationContent.vue +24 -0
  357. package/src/components/ui/pagination/PaginationEllipsis.vue +27 -0
  358. package/src/components/ui/pagination/PaginationFirst.vue +33 -0
  359. package/src/components/ui/pagination/PaginationItem.vue +39 -0
  360. package/src/components/ui/pagination/PaginationLast.vue +33 -0
  361. package/src/components/ui/pagination/PaginationNext.vue +33 -0
  362. package/src/components/ui/pagination/PaginationPrevious.vue +33 -0
  363. package/src/components/ui/pagination/index.ts +8 -0
  364. package/src/components/ui/profile/Profile.vue +226 -0
  365. package/src/components/ui/profile/ProfileGroup.vue +96 -0
  366. package/src/components/ui/profile/index.ts +8 -0
  367. package/src/components/ui/progress/Progress.vue +271 -0
  368. package/src/components/ui/progress/index.ts +9 -0
  369. package/src/components/ui/prompt-input/PromptInput.vue +1094 -0
  370. package/src/components/ui/prompt-input/index.ts +14 -0
  371. package/src/components/ui/prompt-input/types.ts +78 -0
  372. package/src/components/ui/radio-group/RadioGroup.vue +36 -0
  373. package/src/components/ui/radio-group/RadioGroupItem.vue +45 -0
  374. package/src/components/ui/radio-group/RadioGroupOption.vue +80 -0
  375. package/src/components/ui/radio-group/index.ts +3 -0
  376. package/src/components/ui/reasoning/Reasoning.vue +278 -0
  377. package/src/components/ui/reasoning/index.ts +8 -0
  378. package/src/components/ui/reasoning/types.ts +29 -0
  379. package/src/components/ui/select/Select.vue +19 -0
  380. package/src/components/ui/select/SelectContent.vue +166 -0
  381. package/src/components/ui/select/SelectGroup.vue +23 -0
  382. package/src/components/ui/select/SelectItem.vue +97 -0
  383. package/src/components/ui/select/SelectItemText.vue +15 -0
  384. package/src/components/ui/select/SelectLabel.vue +17 -0
  385. package/src/components/ui/select/SelectScrollDownButton.vue +26 -0
  386. package/src/components/ui/select/SelectScrollUpButton.vue +26 -0
  387. package/src/components/ui/select/SelectSeparator.vue +19 -0
  388. package/src/components/ui/select/SelectTrigger.vue +33 -0
  389. package/src/components/ui/select/SelectValue.vue +15 -0
  390. package/src/components/ui/select/index.ts +11 -0
  391. package/src/components/ui/select/search.ts +26 -0
  392. package/src/components/ui/separator/Separator.vue +30 -0
  393. package/src/components/ui/separator/index.ts +5 -0
  394. package/src/components/ui/separator/types.ts +9 -0
  395. package/src/components/ui/shimmer/Shimmer.vue +110 -0
  396. package/src/components/ui/shimmer/index.ts +5 -0
  397. package/src/components/ui/sidebar/Sidebar.vue +142 -0
  398. package/src/components/ui/sidebar/SidebarContent.vue +18 -0
  399. package/src/components/ui/sidebar/SidebarFooter.vue +18 -0
  400. package/src/components/ui/sidebar/SidebarGroup.vue +18 -0
  401. package/src/components/ui/sidebar/SidebarGroupAction.vue +31 -0
  402. package/src/components/ui/sidebar/SidebarGroupContent.vue +18 -0
  403. package/src/components/ui/sidebar/SidebarGroupLabel.vue +30 -0
  404. package/src/components/ui/sidebar/SidebarHeader.vue +18 -0
  405. package/src/components/ui/sidebar/SidebarInput.vue +26 -0
  406. package/src/components/ui/sidebar/SidebarInset.vue +23 -0
  407. package/src/components/ui/sidebar/SidebarMenu.vue +18 -0
  408. package/src/components/ui/sidebar/SidebarMenuAction.vue +34 -0
  409. package/src/components/ui/sidebar/SidebarMenuBadge.vue +25 -0
  410. package/src/components/ui/sidebar/SidebarMenuButton.vue +37 -0
  411. package/src/components/ui/sidebar/SidebarMenuButtonChild.vue +38 -0
  412. package/src/components/ui/sidebar/SidebarMenuItem.vue +18 -0
  413. package/src/components/ui/sidebar/SidebarMenuSub.vue +18 -0
  414. package/src/components/ui/sidebar/SidebarMenuSubButton.vue +36 -0
  415. package/src/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
  416. package/src/components/ui/sidebar/SidebarProvider.vue +119 -0
  417. package/src/components/ui/sidebar/SidebarRail.vue +35 -0
  418. package/src/components/ui/sidebar/SidebarSeparator.vue +18 -0
  419. package/src/components/ui/sidebar/SidebarTrigger.vue +28 -0
  420. package/src/components/ui/sidebar/context.ts +39 -0
  421. package/src/components/ui/sidebar/index.ts +43 -0
  422. package/src/components/ui/sidebar/types.ts +13 -0
  423. package/src/components/ui/sidebar/variants.ts +25 -0
  424. package/src/components/ui/skeleton/Skeleton.vue +53 -0
  425. package/src/components/ui/skeleton/index.ts +5 -0
  426. package/src/components/ui/sonner/Sonner.vue +69 -0
  427. package/src/components/ui/sonner/index.ts +12 -0
  428. package/src/components/ui/spinner/Spinner.vue +33 -0
  429. package/src/components/ui/spinner/index.ts +1 -0
  430. package/src/components/ui/stepper/Stepper.vue +29 -0
  431. package/src/components/ui/stepper/StepperDescription.vue +30 -0
  432. package/src/components/ui/stepper/StepperIndicator.vue +50 -0
  433. package/src/components/ui/stepper/StepperItem.vue +28 -0
  434. package/src/components/ui/stepper/StepperSeparator.vue +25 -0
  435. package/src/components/ui/stepper/StepperTitle.vue +27 -0
  436. package/src/components/ui/stepper/StepperTrigger.vue +27 -0
  437. package/src/components/ui/stepper/index.ts +7 -0
  438. package/src/components/ui/switch/Switch.vue +41 -0
  439. package/src/components/ui/switch/index.ts +1 -0
  440. package/src/components/ui/table/Table.vue +23 -0
  441. package/src/components/ui/table/TableBody.vue +17 -0
  442. package/src/components/ui/table/TableCaption.vue +17 -0
  443. package/src/components/ui/table/TableCell.vue +24 -0
  444. package/src/components/ui/table/TableEmpty.vue +31 -0
  445. package/src/components/ui/table/TableFooter.vue +17 -0
  446. package/src/components/ui/table/TableHead.vue +22 -0
  447. package/src/components/ui/table/TableHeader.vue +17 -0
  448. package/src/components/ui/table/TableRow.vue +22 -0
  449. package/src/components/ui/table/index.ts +9 -0
  450. package/src/components/ui/tabs/Tabs.vue +24 -0
  451. package/src/components/ui/tabs/TabsContent.vue +22 -0
  452. package/src/components/ui/tabs/TabsList.vue +27 -0
  453. package/src/components/ui/tabs/TabsTrigger.vue +27 -0
  454. package/src/components/ui/tabs/index.ts +4 -0
  455. package/src/components/ui/tag/Tag.vue +55 -0
  456. package/src/components/ui/tag/index.ts +2 -0
  457. package/src/components/ui/tag/variants.ts +29 -0
  458. package/src/components/ui/textarea/Textarea.vue +159 -0
  459. package/src/components/ui/textarea/TextareaControl.vue +120 -0
  460. package/src/components/ui/textarea/TextareaFieldGroup.vue +14 -0
  461. package/src/components/ui/textarea/index.ts +10 -0
  462. package/src/components/ui/textarea/types.ts +35 -0
  463. package/src/components/ui/tool/Tool.vue +304 -0
  464. package/src/components/ui/tool/index.ts +7 -0
  465. package/src/components/ui/tooltip/Tooltip.vue +19 -0
  466. package/src/components/ui/tooltip/TooltipContent.vue +44 -0
  467. package/src/components/ui/tooltip/TooltipProvider.vue +14 -0
  468. package/src/components/ui/tooltip/TooltipTrigger.vue +15 -0
  469. package/src/components/ui/tooltip/index.ts +4 -0
  470. package/src/lib/code-highlight.ts +220 -0
  471. package/src/lib/utils.ts +6 -0
  472. package/src/styles.css +684 -0
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://shadcn-vue.com/schema/registry-item.json",
3
+ "name": "network-graph",
4
+ "title": "Network Graph",
5
+ "description": "An Obsidian-style force-directed network graph with zoom, pan, node dragging, selection, and connected-node highlighting.",
6
+ "dependencies": [
7
+ "@lucide/vue",
8
+ "clsx",
9
+ "d3-force",
10
+ "tailwind-merge"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "src/components/ui/network-graph/NetworkGraph.vue",
15
+ "content": "<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\"\nimport type { HTMLAttributes } from \"vue\"\nimport {\n forceCenter,\n forceCollide,\n forceLink,\n forceManyBody,\n forceSimulation,\n forceX,\n forceY,\n type Simulation,\n type SimulationLinkDatum,\n type SimulationNodeDatum,\n} from \"d3-force\"\nimport {\n FocusIcon,\n MinusIcon,\n PlusIcon,\n} from \"@lucide/vue\"\nimport { cn } from \"@/lib/utils\"\n\nexport type NetworkGraphSize = \"sm\" | \"default\" | \"lg\"\n\nexport interface NetworkGraphNode {\n color?: string\n fixed?: boolean\n group?: string\n id: string\n label?: string\n metadata?: Record<string, unknown>\n size?: number\n value?: number\n x?: number\n y?: number\n}\n\nexport interface NetworkGraphLink {\n color?: string\n id?: string\n label?: string\n source: string\n target: string\n value?: number\n}\n\nexport interface NetworkGraphSelectPayload {\n connectedNodeIds: string[]\n index: number\n links: NetworkGraphLink[]\n node: NetworkGraphNode\n}\n\ninterface NetworkGraphProps {\n chargeStrength?: number\n class?: HTMLAttributes[\"class\"]\n collisionPadding?: number\n description?: string\n draggable?: boolean\n emptyLabel?: string\n height?: number\n linkDistance?: number\n links?: NetworkGraphLink[]\n maxZoom?: number\n minZoom?: number\n modelValue?: string\n nodes?: NetworkGraphNode[]\n pannable?: boolean\n selectable?: boolean\n showControls?: boolean\n showLabels?: boolean\n size?: NetworkGraphSize\n summary?: string\n title?: string\n}\n\ninterface GraphNodeDatum extends SimulationNodeDatum {\n color: string\n group?: string\n id: string\n index: number\n label: string\n original: NetworkGraphNode\n radius: number\n}\n\ninterface GraphLinkDatum extends SimulationLinkDatum<GraphNodeDatum> {\n color?: string\n id: string\n label?: string\n original: NetworkGraphLink\n source: string | GraphNodeDatum\n sourceId: string\n target: string | GraphNodeDatum\n targetId: string\n value: number\n}\n\nconst props = withDefaults(defineProps<NetworkGraphProps>(), {\n chargeStrength: -260,\n collisionPadding: 6,\n draggable: true,\n emptyLabel: \"No network data.\",\n linkDistance: 96,\n maxZoom: 2.5,\n minZoom: 0.45,\n nodes: () => [],\n links: () => [],\n pannable: true,\n selectable: true,\n showControls: true,\n showLabels: true,\n size: \"default\",\n})\n\nconst emit = defineEmits<{\n \"select\": [payload: NetworkGraphSelectPayload]\n \"update:modelValue\": [value: string]\n}>()\n\nconst DEFAULT_GRAPH_WIDTH = 900\nconst MIN_GRAPH_WIDTH = 320\nconst graphRef = ref<SVGSVGElement | null>(null)\nconst graphWidth = ref(DEFAULT_GRAPH_WIDTH)\nconst graphNodes = ref<GraphNodeDatum[]>([])\nconst graphLinks = ref<GraphLinkDatum[]>([])\nconst internalSelectedId = ref<string | undefined>()\nconst renderTick = ref(0)\nconst transform = ref({\n k: 1,\n x: 0,\n y: 0,\n})\n\nlet simulation: Simulation<GraphNodeDatum, GraphLinkDatum> | undefined\nlet resizeObserver: ResizeObserver | undefined\nlet pointerMode: \"node\" | \"pan\" | undefined\nlet activeNode: GraphNodeDatum | undefined\nlet panStart:\n | {\n clientX: number\n clientY: number\n x: number\n y: number\n }\n | undefined\n\nconst defaultNodeColors = [\n \"oklch(0.58 0.19 248)\",\n \"oklch(0.6 0.16 153)\",\n \"oklch(0.67 0.18 69)\",\n \"oklch(0.59 0.21 338)\",\n \"oklch(0.62 0.18 204)\",\n \"oklch(0.58 0.2 27)\",\n]\n\nconst sizeClasses = computed(() => {\n if (props.size === \"sm\") {\n return {\n body: \"p-3\",\n control: \"size-7\",\n description: \"text-xs\",\n empty: \"min-h-56\",\n header: \"gap-2 px-3 py-2.5\",\n height: 260,\n label: \"text-[10px]\",\n meta: \"text-[11px]\",\n title: \"text-xs\",\n }\n }\n\n if (props.size === \"lg\") {\n return {\n body: \"p-5\",\n control: \"size-8\",\n description: \"text-sm\",\n empty: \"min-h-[28rem]\",\n header: \"gap-3 px-5 py-4\",\n height: 520,\n label: \"text-xs\",\n meta: \"text-xs\",\n title: \"text-sm\",\n }\n }\n\n return {\n body: \"p-4\",\n control: \"size-8\",\n description: \"text-sm\",\n empty: \"min-h-80\",\n header: \"gap-2.5 px-4 py-3\",\n height: 400,\n label: \"text-[11px]\",\n meta: \"text-xs\",\n title: \"text-[13px]\",\n }\n})\n\nconst graphHeight = computed(() =>\n Math.max(220, Math.trunc(props.height ?? sizeClasses.value.height)),\n)\nconst hasHeader = computed(() =>\n Boolean(props.title || props.description || props.summary),\n)\nconst hasRenderableData = computed(() =>\n graphNodes.value.length > 0,\n)\nconst selectedId = computed(() =>\n props.modelValue ?? internalSelectedId.value,\n)\nconst graphTransform = computed(() =>\n `translate(${transform.value.x} ${transform.value.y}) scale(${transform.value.k})`,\n)\nconst nodeById = computed(() => {\n const map = new Map<string, GraphNodeDatum>()\n\n for (const node of graphNodes.value) {\n map.set(node.id, node)\n }\n\n return map\n})\nconst connectedNodeIds = computed(() => {\n const selected = selectedId.value\n const ids = new Set<string>()\n\n if (!selected) return ids\n\n ids.add(selected)\n\n for (const link of graphLinks.value) {\n if (link.sourceId === selected) ids.add(link.targetId)\n if (link.targetId === selected) ids.add(link.sourceId)\n }\n\n return ids\n})\nconst selectedNode = computed(() =>\n selectedId.value ? nodeById.value.get(selectedId.value) : undefined,\n)\nconst selectedNodeLinks = computed(() =>\n selectedId.value\n ? graphLinks.value.filter((link) => link.sourceId === selectedId.value || link.targetId === selectedId.value)\n : [],\n)\nconst formattedZoom = computed(() =>\n `${Math.round(transform.value.k * 100)}%`,\n)\nconst graphStats = computed(() => {\n const nodes = graphNodes.value.length\n const links = graphLinks.value.length\n\n return `${nodes} nodes · ${links} links`\n})\nconst selectedSummaryText = computed(() => {\n if (!selectedNode.value) return graphStats.value\n\n const connectedCount = Math.max(0, connectedNodeIds.value.size - 1)\n const linkCount = selectedNodeLinks.value.length\n\n return `${connectedCount} connected · ${linkCount} links`\n})\nwatch(\n () => [\n props.nodes,\n props.links,\n props.chargeStrength,\n props.collisionPadding,\n props.height,\n props.linkDistance,\n props.size,\n graphWidth.value,\n ],\n () => rebuildGraph(),\n {\n deep: true,\n immediate: true,\n },\n)\n\nwatch(\n graphRef,\n (svgElement) => {\n resizeObserver?.disconnect()\n resizeObserver = undefined\n\n if (!svgElement) return\n\n const updateGraphWidth = () => {\n const rect = svgElement.getBoundingClientRect()\n const nextWidth = Math.trunc(clamp(rect.width || DEFAULT_GRAPH_WIDTH, MIN_GRAPH_WIDTH, DEFAULT_GRAPH_WIDTH))\n\n if (graphWidth.value !== nextWidth) {\n graphWidth.value = nextWidth\n }\n }\n\n updateGraphWidth()\n\n if (typeof ResizeObserver === \"undefined\") return\n\n resizeObserver = new ResizeObserver(updateGraphWidth)\n resizeObserver.observe(svgElement)\n },\n {\n flush: \"post\",\n },\n)\n\nonBeforeUnmount(() => {\n simulation?.stop()\n resizeObserver?.disconnect()\n})\n\nfunction rebuildGraph() {\n simulation?.stop()\n\n const nodes = createGraphNodes()\n const nodeIds = new Set(nodes.map((node) => node.id))\n const links = createGraphLinks(nodeIds)\n\n graphNodes.value = nodes\n graphLinks.value = links\n\n if (nodes.length === 0) return\n\n simulation = forceSimulation<GraphNodeDatum>(nodes)\n .force(\n \"link\",\n forceLink<GraphNodeDatum, GraphLinkDatum>(links)\n .id((node) => node.id)\n .distance(props.linkDistance)\n .strength(0.45),\n )\n .force(\"charge\", forceManyBody<GraphNodeDatum>().strength(props.chargeStrength))\n .force(\"center\", forceCenter(graphWidth.value / 2, graphHeight.value / 2))\n .force(\"x\", forceX<GraphNodeDatum>(graphWidth.value / 2).strength(0.045))\n .force(\"y\", forceY<GraphNodeDatum>(graphHeight.value / 2).strength(0.045))\n .force(\n \"collide\",\n forceCollide<GraphNodeDatum>()\n .radius((node) => node.radius + props.collisionPadding + (props.showLabels ? 18 : 0))\n .strength(0.88),\n )\n .on(\"tick\", () => {\n constrainNodePositions()\n renderTick.value += 1\n })\n}\n\nfunction createGraphNodes() {\n const count = Math.max(1, props.nodes.length)\n const radius = Math.min(graphWidth.value, graphHeight.value) * 0.34\n\n return props.nodes.map((node, index): GraphNodeDatum => {\n const angle = (index / count) * Math.PI * 2\n const x = getInitialNodeX(node, angle, radius)\n const y = getInitialNodeY(node, angle, radius)\n const graphNode: GraphNodeDatum = {\n ...node,\n color: getNodeColor(node, index),\n id: node.id,\n index,\n label: node.label ?? node.id,\n original: node,\n radius: getNodeRadius(node),\n x,\n y,\n }\n\n if (node.fixed) {\n graphNode.fx = x\n graphNode.fy = y\n }\n\n return graphNode\n })\n}\n\nfunction getInitialNodeX(node: NetworkGraphNode, angle: number, radius: number) {\n const x = typeof node.x === \"number\"\n ? node.x * (graphWidth.value / DEFAULT_GRAPH_WIDTH)\n : (graphWidth.value / 2) + Math.cos(angle) * radius\n\n return clampNodeX(x, getNodeRadius(node))\n}\n\nfunction getInitialNodeY(node: NetworkGraphNode, angle: number, radius: number) {\n const y = typeof node.y === \"number\"\n ? node.y\n : (graphHeight.value / 2) + Math.sin(angle) * radius\n\n return clampNodeY(y, getNodeRadius(node))\n}\n\nfunction createGraphLinks(nodeIds: Set<string>) {\n return props.links\n .filter((link) => nodeIds.has(link.source) && nodeIds.has(link.target))\n .map((link, index): GraphLinkDatum => ({\n ...link,\n id: link.id ?? `${link.source}-${link.target}-${index}`,\n original: link,\n source: link.source,\n sourceId: link.source,\n target: link.target,\n targetId: link.target,\n value: Math.max(1, link.value ?? 1),\n }))\n}\n\nfunction getNodeRadius(node: NetworkGraphNode) {\n if (typeof node.size === \"number\" && Number.isFinite(node.size)) {\n return clamp(node.size, 7, 28)\n }\n\n return clamp(8 + Math.sqrt(Math.max(0, node.value ?? 1)) * 2.5, 8, 24)\n}\n\nfunction getNodeColor(node: NetworkGraphNode, index: number) {\n if (node.color) return node.color\n\n const colorIndex = node.group\n ? Math.abs(hashString(node.group)) % defaultNodeColors.length\n : index % defaultNodeColors.length\n\n return defaultNodeColors[colorIndex] ?? defaultNodeColors[0]\n}\n\nfunction getLinkSource(link: GraphLinkDatum) {\n return typeof link.source === \"string\" ? nodeById.value.get(link.source) : link.source\n}\n\nfunction getLinkTarget(link: GraphLinkDatum) {\n return typeof link.target === \"string\" ? nodeById.value.get(link.target) : link.target\n}\n\nfunction isSelectedNode(node: GraphNodeDatum) {\n return selectedId.value === node.id\n}\n\nfunction isDimmedNode(node: GraphNodeDatum) {\n return Boolean(selectedId.value && !connectedNodeIds.value.has(node.id))\n}\n\nfunction isDimmedLink(link: GraphLinkDatum) {\n return Boolean(\n selectedId.value &&\n link.sourceId !== selectedId.value &&\n link.targetId !== selectedId.value,\n )\n}\n\nfunction linkStrokeWidth(link: GraphLinkDatum) {\n const width = Math.min(4, 1 + Math.sqrt(link.value) * 0.35)\n\n if (!selectedId.value || isDimmedLink(link)) return width\n\n return Math.min(4.5, width + 0.35)\n}\n\nfunction linkStroke(link: GraphLinkDatum) {\n if (!selectedId.value || isDimmedLink(link)) {\n return link.color ?? \"var(--border)\"\n }\n\n return link.color ?? \"var(--foreground)\"\n}\n\nfunction linkOpacity(link: GraphLinkDatum) {\n if (!selectedId.value) return 0.22\n\n return isDimmedLink(link) ? 0.1 : 0.78\n}\n\nfunction nodeOpacity(node: GraphNodeDatum) {\n return isDimmedNode(node) ? 0.32 : 1\n}\n\nfunction nodeStroke() {\n return \"var(--background)\"\n}\n\nfunction constrainNodePositions() {\n for (const node of graphNodes.value) {\n node.x = clampNodeX(node.x ?? graphWidth.value / 2, node.radius)\n node.y = clampNodeY(node.y ?? graphHeight.value / 2, node.radius)\n }\n}\n\nfunction clampNodeX(value: number, radius: number) {\n const padding = radius + 28\n const max = Math.max(padding, graphWidth.value - padding)\n\n return clamp(value, padding, max)\n}\n\nfunction clampNodeY(value: number, radius: number) {\n const padding = radius + 34\n const max = Math.max(padding, graphHeight.value - padding)\n\n return clamp(value, padding, max)\n}\n\nfunction selectNode(node: GraphNodeDatum) {\n if (!props.selectable) return\n\n internalSelectedId.value = node.id\n emit(\"update:modelValue\", node.id)\n emit(\"select\", {\n connectedNodeIds: Array.from(getConnectedIds(node.id)),\n index: node.index,\n links: props.links.filter((link) => link.source === node.id || link.target === node.id),\n node: node.original,\n })\n}\n\nfunction getConnectedIds(id: string) {\n const ids = new Set<string>([id])\n\n for (const link of graphLinks.value) {\n if (link.sourceId === id) ids.add(link.targetId)\n if (link.targetId === id) ids.add(link.sourceId)\n }\n\n return ids\n}\n\nfunction handleWheel(event: WheelEvent) {\n const svgPoint = getSvgPoint(event)\n const previous = transform.value\n const nextZoom = clamp(\n previous.k * (event.deltaY < 0 ? 1.12 : 0.88),\n props.minZoom,\n props.maxZoom,\n )\n const ratio = nextZoom / previous.k\n\n transform.value = {\n k: nextZoom,\n x: svgPoint.x - (svgPoint.x - previous.x) * ratio,\n y: svgPoint.y - (svgPoint.y - previous.y) * ratio,\n }\n}\n\nfunction handleCanvasPointerDown(event: PointerEvent) {\n if (!props.pannable || pointerMode) return\n\n pointerMode = \"pan\"\n panStart = {\n clientX: event.clientX,\n clientY: event.clientY,\n x: transform.value.x,\n y: transform.value.y,\n }\n graphRef.value?.setPointerCapture(event.pointerId)\n}\n\nfunction handleNodePointerDown(event: PointerEvent, node: GraphNodeDatum) {\n event.stopPropagation()\n selectNode(node)\n\n if (!props.draggable) return\n\n pointerMode = \"node\"\n activeNode = node\n node.fx = node.x\n node.fy = node.y\n simulation?.alphaTarget(0.22).restart()\n graphRef.value?.setPointerCapture(event.pointerId)\n}\n\nfunction handlePointerMove(event: PointerEvent) {\n if (pointerMode === \"node\" && activeNode) {\n const point = getGraphPoint(event)\n\n activeNode.fx = clampNodeX(point.x, activeNode.radius)\n activeNode.fy = clampNodeY(point.y, activeNode.radius)\n renderTick.value += 1\n return\n }\n\n if (pointerMode === \"pan\" && panStart) {\n const delta = getSvgDelta(event, panStart.clientX, panStart.clientY)\n\n transform.value = {\n ...transform.value,\n x: panStart.x + delta.x,\n y: panStart.y + delta.y,\n }\n }\n}\n\nfunction handlePointerUp(event: PointerEvent) {\n if (pointerMode === \"node\" && activeNode) {\n if (!activeNode.original.fixed) {\n activeNode.fx = undefined\n activeNode.fy = undefined\n }\n\n simulation?.alphaTarget(0)\n }\n\n pointerMode = undefined\n activeNode = undefined\n panStart = undefined\n graphRef.value?.releasePointerCapture(event.pointerId)\n}\n\nfunction zoomBy(multiplier: number) {\n const nextZoom = clamp(transform.value.k * multiplier, props.minZoom, props.maxZoom)\n\n transform.value = {\n ...transform.value,\n k: nextZoom,\n }\n}\n\nfunction resetView() {\n transform.value = {\n k: 1,\n x: 0,\n y: 0,\n }\n}\n\nfunction getSvgPoint(event: Pick<MouseEvent, \"clientX\" | \"clientY\">) {\n const rect = graphRef.value?.getBoundingClientRect()\n\n if (!rect) {\n return {\n x: graphWidth.value / 2,\n y: graphHeight.value / 2,\n }\n }\n\n return {\n x: ((event.clientX - rect.left) / rect.width) * graphWidth.value,\n y: ((event.clientY - rect.top) / rect.height) * graphHeight.value,\n }\n}\n\nfunction getGraphPoint(event: Pick<MouseEvent, \"clientX\" | \"clientY\">) {\n const point = getSvgPoint(event)\n\n return {\n x: (point.x - transform.value.x) / transform.value.k,\n y: (point.y - transform.value.y) / transform.value.k,\n }\n}\n\nfunction getSvgDelta(event: Pick<MouseEvent, \"clientX\" | \"clientY\">, startX: number, startY: number) {\n const rect = graphRef.value?.getBoundingClientRect()\n\n if (!rect) {\n return {\n x: 0,\n y: 0,\n }\n }\n\n return {\n x: ((event.clientX - startX) / rect.width) * graphWidth.value,\n y: ((event.clientY - startY) / rect.height) * graphHeight.value,\n }\n}\n\nfunction hashString(value: string) {\n let hash = 0\n\n for (let index = 0; index < value.length; index += 1) {\n hash = ((hash << 5) - hash) + value.charCodeAt(index)\n hash |= 0\n }\n\n return hash\n}\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value))\n}\n</script>\n\n<template>\n <article\n data-slot=\"network-graph\"\n :data-size=\"props.size\"\n :class=\"cn('overflow-hidden rounded-xl border bg-card text-card-foreground shadow-xs', props.class)\"\n >\n <header\n v-if=\"hasHeader\"\n data-slot=\"network-graph-header\"\n :class=\"cn('flex flex-col gap-3 border-b sm:flex-row sm:items-start sm:justify-between', sizeClasses.header)\"\n >\n <div\n v-if=\"props.title || props.description\"\n class=\"flex min-w-0 flex-col gap-1\"\n >\n <h3\n v-if=\"props.title\"\n data-slot=\"network-graph-title\"\n :class=\"cn('truncate font-semibold leading-tight tracking-normal', sizeClasses.title)\"\n >\n {{ props.title }}\n </h3>\n <p\n v-if=\"props.description\"\n data-slot=\"network-graph-description\"\n :class=\"cn('max-w-2xl text-muted-foreground', sizeClasses.description)\"\n >\n {{ props.description }}\n </p>\n </div>\n\n <div\n v-if=\"props.summary || hasRenderableData\"\n data-slot=\"network-graph-summary\"\n :class=\"cn('flex shrink-0 flex-wrap items-center gap-x-2 gap-y-1 text-muted-foreground', sizeClasses.meta)\"\n >\n <span :class=\"cn(props.summary && 'font-medium text-foreground')\">\n {{ props.summary ?? graphStats }}\n </span>\n </div>\n </header>\n\n <div\n data-slot=\"network-graph-body\"\n :class=\"cn('relative min-w-0 bg-background', sizeClasses.body)\"\n :data-tick=\"renderTick\"\n >\n <div\n v-if=\"!hasRenderableData\"\n data-slot=\"network-graph-empty\"\n :class=\"cn('flex items-center justify-center rounded-md border border-dashed bg-muted/20 text-sm text-muted-foreground', sizeClasses.empty)\"\n >\n {{ props.emptyLabel }}\n </div>\n\n <template v-else>\n <div\n data-slot=\"network-graph-surface\"\n class=\"relative min-w-0 overflow-hidden bg-background\"\n >\n <div\n v-if=\"props.showControls\"\n data-slot=\"network-graph-controls\"\n class=\"absolute top-3 right-3 z-10 inline-flex items-center gap-1 rounded-md bg-background/80 p-1 text-xs backdrop-blur\"\n >\n <button\n type=\"button\"\n :class=\"cn('inline-flex items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none', sizeClasses.control)\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n @click=\"zoomBy(1.18)\"\n >\n <PlusIcon class=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n :class=\"cn('inline-flex items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none', sizeClasses.control)\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n @click=\"zoomBy(0.82)\"\n >\n <MinusIcon class=\"size-3.5\" />\n </button>\n <span\n data-slot=\"network-graph-zoom\"\n class=\"hidden min-w-10 text-center font-medium tabular-nums text-muted-foreground sm:inline\"\n >\n {{ formattedZoom }}\n </span>\n <button\n type=\"button\"\n :class=\"cn('inline-flex items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none', sizeClasses.control)\"\n aria-label=\"Reset view\"\n title=\"Reset view\"\n @click=\"resetView\"\n >\n <FocusIcon class=\"size-3.5\" />\n </button>\n </div>\n\n <svg\n ref=\"graphRef\"\n data-slot=\"network-graph-canvas\"\n class=\"block w-full touch-none\"\n :viewBox=\"`0 0 ${graphWidth} ${graphHeight}`\"\n :style=\"{ height: `${graphHeight}px` }\"\n role=\"img\"\n :aria-label=\"props.title ?? 'Network graph'\"\n @pointerdown=\"handleCanvasPointerDown\"\n @pointermove=\"handlePointerMove\"\n @pointerup=\"handlePointerUp\"\n @pointercancel=\"handlePointerUp\"\n @wheel.prevent=\"handleWheel\"\n >\n <rect\n data-slot=\"network-graph-background\"\n width=\"100%\"\n height=\"100%\"\n fill=\"var(--background)\"\n />\n\n <g :transform=\"graphTransform\">\n <g data-slot=\"network-graph-links\">\n <line\n v-for=\"link in graphLinks\"\n :key=\"link.id\"\n data-slot=\"network-graph-link\"\n :x1=\"getLinkSource(link)?.x ?? 0\"\n :y1=\"getLinkSource(link)?.y ?? 0\"\n :x2=\"getLinkTarget(link)?.x ?? 0\"\n :y2=\"getLinkTarget(link)?.y ?? 0\"\n :stroke=\"linkStroke(link)\"\n :stroke-opacity=\"linkOpacity(link)\"\n :stroke-width=\"linkStrokeWidth(link)\"\n stroke-linecap=\"round\"\n />\n </g>\n\n <g data-slot=\"network-graph-nodes\">\n <g\n v-for=\"node in graphNodes\"\n :key=\"node.id\"\n data-slot=\"network-graph-node\"\n :data-selected=\"isSelectedNode(node) ? '' : undefined\"\n :data-dimmed=\"isDimmedNode(node) ? '' : undefined\"\n :transform=\"`translate(${node.x ?? 0} ${node.y ?? 0})`\"\n class=\"cursor-grab outline-none transition-opacity active:cursor-grabbing\"\n :style=\"{ opacity: nodeOpacity(node) }\"\n role=\"button\"\n tabindex=\"0\"\n :aria-label=\"node.label\"\n @click=\"selectNode(node)\"\n @keydown.enter.prevent=\"selectNode(node)\"\n @keydown.space.prevent=\"selectNode(node)\"\n @pointerdown=\"handleNodePointerDown($event, node)\"\n >\n <circle\n data-slot=\"network-graph-node-circle\"\n :r=\"node.radius\"\n :fill=\"node.color\"\n :stroke=\"nodeStroke()\"\n stroke-width=\"1.5\"\n class=\"transition-[stroke,stroke-width]\"\n />\n <circle\n v-if=\"isSelectedNode(node)\"\n data-slot=\"network-graph-node-ring\"\n :r=\"node.radius + 4\"\n fill=\"none\"\n stroke=\"var(--foreground)\"\n stroke-opacity=\"0.32\"\n stroke-width=\"1.5\"\n />\n <text\n v-if=\"props.showLabels\"\n data-slot=\"network-graph-label\"\n :class=\"cn('pointer-events-none select-none fill-current text-center font-semibold text-foreground', sizeClasses.label)\"\n text-anchor=\"middle\"\n :y=\"node.radius + 16\"\n stroke=\"var(--background)\"\n stroke-linejoin=\"round\"\n stroke-width=\"3\"\n paint-order=\"stroke\"\n >\n {{ node.label }}\n </text>\n </g>\n </g>\n </g>\n </svg>\n\n <div\n data-slot=\"network-graph-selection\"\n :class=\"cn('flex min-w-0 flex-col gap-1 border-t bg-muted/20 px-3 py-2.5 sm:flex-row sm:items-center sm:justify-between', sizeClasses.meta)\"\n >\n <span class=\"flex min-w-0 items-center gap-2\">\n <span\n data-slot=\"network-graph-selection-dot\"\n class=\"size-2 shrink-0 rounded-full bg-foreground\"\n :style=\"{ backgroundColor: selectedNode?.color ?? 'var(--muted-foreground)' }\"\n />\n <span\n data-slot=\"network-graph-selection-label\"\n class=\"min-w-0 truncate font-semibold text-foreground\"\n >\n {{ selectedNode?.label ?? \"No node selected\" }}\n </span>\n </span>\n <span\n data-slot=\"network-graph-selection-meta\"\n class=\"min-w-0 text-muted-foreground\"\n >\n {{ selectedSummaryText }}\n </span>\n </div>\n </div>\n </template>\n </div>\n </article>\n</template>\n",
16
+ "type": "registry:ui",
17
+ "target": "components/ui/network-graph/NetworkGraph.vue"
18
+ },
19
+ {
20
+ "path": "src/components/ui/network-graph/index.ts",
21
+ "content": "export { default as NetworkGraph } from \"./NetworkGraph.vue\"\nexport type {\n NetworkGraphLink,\n NetworkGraphNode,\n NetworkGraphSelectPayload,\n NetworkGraphSize,\n} from \"./NetworkGraph.vue\"\n",
22
+ "type": "registry:ui",
23
+ "target": "components/ui/network-graph/index.ts"
24
+ },
25
+ {
26
+ "path": "src/lib/utils.ts",
27
+ "content": "import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
28
+ "type": "registry:lib",
29
+ "target": "lib/utils.ts"
30
+ }
31
+ ],
32
+ "type": "registry:ui"
33
+ }
@@ -0,0 +1,95 @@
1
+ {
2
+ "$schema": "https://shadcn-vue.com/schema/registry-item.json",
3
+ "name": "pagination",
4
+ "title": "Pagination",
5
+ "description": "A page navigation control with previous, next, first, last, active, disabled, and ellipsis states.",
6
+ "dependencies": [
7
+ "@lucide/vue",
8
+ "@vueuse/core",
9
+ "class-variance-authority",
10
+ "clsx",
11
+ "reka-ui",
12
+ "tailwind-merge"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/pagination/Pagination.vue",
17
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationRootEmits, PaginationRootProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationRoot, useForwardPropsEmits } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\n\nconst props = defineProps<PaginationRootProps & {\n class?: HTMLAttributes[\"class\"]\n}>()\nconst emits = defineEmits<PaginationRootEmits>()\n\nconst delegatedProps = reactiveOmit(props, \"class\")\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <PaginationRoot\n v-slot=\"slotProps\"\n data-slot=\"pagination\"\n v-bind=\"forwarded\"\n :class=\"cn('mx-auto flex w-full justify-center', props.class)\"\n >\n <slot v-bind=\"slotProps\" />\n </PaginationRoot>\n</template>\n",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/pagination/Pagination.vue"
20
+ },
21
+ {
22
+ "path": "src/components/ui/pagination/PaginationContent.vue",
23
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationListProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationList } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\n\nconst props = defineProps<PaginationListProps & {\n class?: HTMLAttributes[\"class\"]\n}>()\n\nconst delegatedProps = reactiveOmit(props, \"class\")\n</script>\n\n<template>\n <PaginationList\n v-slot=\"slotProps\"\n data-slot=\"pagination-content\"\n v-bind=\"delegatedProps\"\n :class=\"cn('flex flex-row items-center gap-1', props.class)\"\n >\n <slot v-bind=\"slotProps\" />\n </PaginationList>\n</template>\n",
24
+ "type": "registry:ui",
25
+ "target": "components/ui/pagination/PaginationContent.vue"
26
+ },
27
+ {
28
+ "path": "src/components/ui/pagination/PaginationEllipsis.vue",
29
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationEllipsisProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport { MoreHorizontalIcon } from \"@lucide/vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationEllipsis } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\n\nconst props = defineProps<PaginationEllipsisProps & {\n class?: HTMLAttributes[\"class\"]\n}>()\n\nconst delegatedProps = reactiveOmit(props, \"class\")\n</script>\n\n<template>\n <PaginationEllipsis\n data-slot=\"pagination-ellipsis\"\n v-bind=\"delegatedProps\"\n :class=\"cn('flex size-9 items-center justify-center', props.class)\"\n >\n <slot>\n <MoreHorizontalIcon class=\"size-4\" />\n <span class=\"sr-only\">More pages</span>\n </slot>\n </PaginationEllipsis>\n</template>\n",
30
+ "type": "registry:ui",
31
+ "target": "components/ui/pagination/PaginationEllipsis.vue"
32
+ },
33
+ {
34
+ "path": "src/components/ui/pagination/PaginationFirst.vue",
35
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationFirstProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport type { ButtonVariants } from \"@/components/ui/button\"\nimport { ChevronsLeftIcon } from \"@lucide/vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationFirst, useForwardProps } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst props = withDefaults(defineProps<PaginationFirstProps & {\n class?: HTMLAttributes[\"class\"]\n size?: ButtonVariants[\"size\"]\n}>(), {\n size: \"default\",\n})\n\nconst delegatedProps = reactiveOmit(props, \"class\", \"size\")\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <PaginationFirst\n data-slot=\"pagination-first\"\n v-bind=\"forwarded\"\n :class=\"cn(buttonVariants({ variant: 'ghost', size: props.size }), 'gap-1 px-2.5', props.class)\"\n >\n <slot>\n <ChevronsLeftIcon />\n <span class=\"hidden sm:block\">First</span>\n </slot>\n </PaginationFirst>\n</template>\n",
36
+ "type": "registry:ui",
37
+ "target": "components/ui/pagination/PaginationFirst.vue"
38
+ },
39
+ {
40
+ "path": "src/components/ui/pagination/PaginationItem.vue",
41
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationListItemProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport type { ButtonVariants } from \"@/components/ui/button\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationListItem } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst props = withDefaults(defineProps<PaginationListItemProps & {\n class?: HTMLAttributes[\"class\"]\n isActive?: boolean\n size?: ButtonVariants[\"size\"]\n}>(), {\n isActive: false,\n size: \"icon\",\n})\n\nconst delegatedProps = reactiveOmit(props, \"class\", \"isActive\", \"size\")\n</script>\n\n<template>\n <PaginationListItem\n data-slot=\"pagination-item\"\n v-bind=\"delegatedProps\"\n :class=\"\n cn(\n buttonVariants({\n variant: props.isActive ? 'outline' : 'ghost',\n size: props.size,\n }),\n !props.isActive && 'data-[selected=true]:border data-[selected=true]:border-input data-[selected=true]:bg-background data-[selected=true]:shadow-xs',\n props.class,\n )\n \"\n >\n <slot />\n </PaginationListItem>\n</template>\n",
42
+ "type": "registry:ui",
43
+ "target": "components/ui/pagination/PaginationItem.vue"
44
+ },
45
+ {
46
+ "path": "src/components/ui/pagination/PaginationLast.vue",
47
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationLastProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport type { ButtonVariants } from \"@/components/ui/button\"\nimport { ChevronsRightIcon } from \"@lucide/vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationLast, useForwardProps } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst props = withDefaults(defineProps<PaginationLastProps & {\n class?: HTMLAttributes[\"class\"]\n size?: ButtonVariants[\"size\"]\n}>(), {\n size: \"default\",\n})\n\nconst delegatedProps = reactiveOmit(props, \"class\", \"size\")\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <PaginationLast\n data-slot=\"pagination-last\"\n v-bind=\"forwarded\"\n :class=\"cn(buttonVariants({ variant: 'ghost', size: props.size }), 'gap-1 px-2.5', props.class)\"\n >\n <slot>\n <span class=\"hidden sm:block\">Last</span>\n <ChevronsRightIcon />\n </slot>\n </PaginationLast>\n</template>\n",
48
+ "type": "registry:ui",
49
+ "target": "components/ui/pagination/PaginationLast.vue"
50
+ },
51
+ {
52
+ "path": "src/components/ui/pagination/PaginationNext.vue",
53
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationNextProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport type { ButtonVariants } from \"@/components/ui/button\"\nimport { ChevronRightIcon } from \"@lucide/vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationNext, useForwardProps } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst props = withDefaults(defineProps<PaginationNextProps & {\n class?: HTMLAttributes[\"class\"]\n size?: ButtonVariants[\"size\"]\n}>(), {\n size: \"default\",\n})\n\nconst delegatedProps = reactiveOmit(props, \"class\", \"size\")\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <PaginationNext\n data-slot=\"pagination-next\"\n v-bind=\"forwarded\"\n :class=\"cn(buttonVariants({ variant: 'ghost', size: props.size }), 'gap-1 px-2.5', props.class)\"\n >\n <slot>\n <span class=\"hidden sm:block\">Next</span>\n <ChevronRightIcon />\n </slot>\n </PaginationNext>\n</template>\n",
54
+ "type": "registry:ui",
55
+ "target": "components/ui/pagination/PaginationNext.vue"
56
+ },
57
+ {
58
+ "path": "src/components/ui/pagination/PaginationPrevious.vue",
59
+ "content": "<script setup lang=\"ts\">\nimport type { PaginationPrevProps } from \"reka-ui\"\nimport type { HTMLAttributes } from \"vue\"\nimport type { ButtonVariants } from \"@/components/ui/button\"\nimport { ChevronLeftIcon } from \"@lucide/vue\"\nimport { reactiveOmit } from \"@vueuse/core\"\nimport { PaginationPrev, useForwardProps } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst props = withDefaults(defineProps<PaginationPrevProps & {\n class?: HTMLAttributes[\"class\"]\n size?: ButtonVariants[\"size\"]\n}>(), {\n size: \"default\",\n})\n\nconst delegatedProps = reactiveOmit(props, \"class\", \"size\")\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <PaginationPrev\n data-slot=\"pagination-previous\"\n v-bind=\"forwarded\"\n :class=\"cn(buttonVariants({ variant: 'ghost', size: props.size }), 'gap-1 px-2.5', props.class)\"\n >\n <slot>\n <ChevronLeftIcon />\n <span class=\"hidden sm:block\">Previous</span>\n </slot>\n </PaginationPrev>\n</template>\n",
60
+ "type": "registry:ui",
61
+ "target": "components/ui/pagination/PaginationPrevious.vue"
62
+ },
63
+ {
64
+ "path": "src/components/ui/pagination/index.ts",
65
+ "content": "export { default as Pagination } from \"./Pagination.vue\"\nexport { default as PaginationContent } from \"./PaginationContent.vue\"\nexport { default as PaginationEllipsis } from \"./PaginationEllipsis.vue\"\nexport { default as PaginationFirst } from \"./PaginationFirst.vue\"\nexport { default as PaginationItem } from \"./PaginationItem.vue\"\nexport { default as PaginationLast } from \"./PaginationLast.vue\"\nexport { default as PaginationNext } from \"./PaginationNext.vue\"\nexport { default as PaginationPrevious } from \"./PaginationPrevious.vue\"\n",
66
+ "type": "registry:ui",
67
+ "target": "components/ui/pagination/index.ts"
68
+ },
69
+ {
70
+ "path": "src/components/ui/button/Button.vue",
71
+ "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from \"vue\"\nimport { Primitive, type PrimitiveProps } from \"reka-ui\"\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type ButtonVariants } from \"./variants\"\n\ninterface ButtonProps extends PrimitiveProps {\n variant?: ButtonVariants[\"variant\"]\n size?: ButtonVariants[\"size\"]\n class?: HTMLAttributes[\"class\"]\n}\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n as: \"button\",\n})\n</script>\n\n<template>\n <Primitive\n data-slot=\"button\"\n :as=\"props.as\"\n :as-child=\"props.asChild\"\n :class=\"cn(buttonVariants({ variant: props.variant, size: props.size }), props.class)\"\n >\n <slot />\n </Primitive>\n</template>\n",
72
+ "type": "registry:ui",
73
+ "target": "components/ui/button/Button.vue"
74
+ },
75
+ {
76
+ "path": "src/components/ui/button/variants.ts",
77
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\"\n\nexport const buttonVariants = cva(\n \"inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-[background-color,border-color,color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/30\",\n outline:\n \"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground\",\n secondary: \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n lg: \"h-10 rounded-md px-6\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n)\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>\n",
78
+ "type": "registry:ui",
79
+ "target": "components/ui/button/variants.ts"
80
+ },
81
+ {
82
+ "path": "src/components/ui/button/index.ts",
83
+ "content": "export { default as Button } from \"./Button.vue\"\nexport { buttonVariants, type ButtonVariants } from \"./variants\"\n",
84
+ "type": "registry:ui",
85
+ "target": "components/ui/button/index.ts"
86
+ },
87
+ {
88
+ "path": "src/lib/utils.ts",
89
+ "content": "import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
90
+ "type": "registry:lib",
91
+ "target": "lib/utils.ts"
92
+ }
93
+ ],
94
+ "type": "registry:ui"
95
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://shadcn-vue.com/schema/registry-item.json",
3
+ "name": "profile",
4
+ "title": "Profile",
5
+ "description": "A profile identity display with fallback, badge, avatar-only, and grouped states.",
6
+ "dependencies": [
7
+ "clsx",
8
+ "tailwind-merge"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "src/components/ui/profile/Profile.vue",
13
+ "content": "<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\"\nimport type { HTMLAttributes } from \"vue\"\nimport { cn } from \"@/lib/utils\"\n\nexport type ProfileBadgePlacement =\n | \"bottom-left\"\n | \"bottom-right\"\n | \"top-left\"\n | \"top-right\"\n\nexport type ProfileBadgeVariant =\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n\nexport type ProfileSize = \"default\" | \"lg\" | \"sm\" | \"xl\" | \"xs\"\n\nconst props = withDefaults(\n defineProps<{\n alt?: string\n avatarOnly?: boolean\n badge?: boolean | number | string\n badgeLabel?: string\n badgePlacement?: ProfileBadgePlacement\n badgeVariant?: ProfileBadgeVariant\n class?: HTMLAttributes[\"class\"]\n contentClass?: HTMLAttributes[\"class\"]\n description?: string\n descriptionClass?: HTMLAttributes[\"class\"]\n fallback?: string\n name?: string\n nameClass?: HTMLAttributes[\"class\"]\n shape?: \"circle\" | \"rounded\"\n size?: ProfileSize\n src?: string\n }>(),\n {\n avatarOnly: false,\n badgePlacement: \"bottom-right\",\n badgeVariant: \"default\",\n shape: \"circle\",\n size: \"default\",\n },\n)\n\nconst imageFailed = ref(false)\n\nwatch(\n () => props.src,\n () => {\n imageFailed.value = false\n },\n)\n\nconst showImage = computed(() => Boolean(props.src) && !imageFailed.value)\nconst showBadge = computed(\n () =>\n props.badge !== undefined &&\n props.badge !== false &&\n props.badge !== null,\n)\nconst badgeText = computed(() => {\n if (props.badge === true) return \"\"\n if (!showBadge.value) return \"\"\n return String(props.badge)\n})\nconst resolvedFallback = computed(() => {\n if (props.fallback) return props.fallback\n\n const source = props.name ?? props.alt ?? \"?\"\n const parts = source.trim().split(/\\s+/).filter(Boolean)\n\n if (parts.length >= 2) {\n return `${Array.from(parts[0])[0] ?? \"\"}${Array.from(parts[1])[0] ?? \"\"}`.toUpperCase()\n }\n\n return Array.from(parts[0] ?? source).slice(0, 2).join(\"\").toUpperCase()\n})\n\nfunction avatarClass() {\n return cn(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden bg-muted font-medium text-muted-foreground\",\n props.shape === \"circle\" ? \"rounded-full\" : \"rounded-md\",\n props.size === \"xs\" && \"size-6 text-[10px]\",\n props.size === \"sm\" && \"size-8 text-xs\",\n props.size === \"default\" && \"size-10 text-sm\",\n props.size === \"lg\" && \"size-12 text-base\",\n props.size === \"xl\" && \"size-14 text-lg\",\n )\n}\n\nfunction contentClasses() {\n return cn(\n \"grid min-w-0 max-w-40 gap-0.5\",\n props.size === \"xs\" && \"gap-0\",\n props.size === \"sm\" && \"gap-0\",\n props.contentClass,\n )\n}\n\nfunction nameClasses() {\n return cn(\n \"truncate font-medium leading-none text-foreground\",\n props.size === \"xs\" && \"text-xs\",\n props.size === \"sm\" && \"text-sm\",\n props.size === \"default\" && \"text-sm\",\n props.size === \"lg\" && \"text-base\",\n props.size === \"xl\" && \"text-base\",\n props.nameClass,\n )\n}\n\nfunction descriptionClasses() {\n return cn(\n \"truncate leading-normal text-muted-foreground\",\n props.size === \"xs\" ? \"text-[10px]\" : \"text-xs\",\n props.descriptionClass,\n )\n}\n\nfunction badgeClass() {\n const hasText = Boolean(badgeText.value)\n\n return cn(\n \"absolute z-10 flex items-center justify-center border-2 border-background font-medium shadow-none\",\n props.badgePlacement === \"bottom-right\" &&\n \"bottom-0 right-0 translate-x-1/4 translate-y-1/4\",\n props.badgePlacement === \"bottom-left\" &&\n \"bottom-0 left-0 -translate-x-1/4 translate-y-1/4\",\n props.badgePlacement === \"top-right\" &&\n \"right-0 top-0 -translate-y-1/4 translate-x-1/4\",\n props.badgePlacement === \"top-left\" &&\n \"left-0 top-0 -translate-x-1/4 -translate-y-1/4\",\n props.badgeVariant === \"default\" && \"bg-primary text-primary-foreground\",\n props.badgeVariant === \"secondary\" &&\n \"bg-secondary text-secondary-foreground\",\n props.badgeVariant === \"destructive\" &&\n \"bg-destructive text-destructive-foreground\",\n props.badgeVariant === \"outline\" && \"bg-background text-foreground\",\n hasText\n ? \"h-5 min-w-5 rounded-full px-1 text-[10px] leading-none\"\n : \"rounded-full\",\n !hasText && props.size === \"xs\" && \"size-2.5\",\n !hasText && props.size === \"sm\" && \"size-3\",\n !hasText && props.size === \"default\" && \"size-3.5\",\n !hasText && props.size === \"lg\" && \"size-4\",\n !hasText && props.size === \"xl\" && \"size-4\",\n )\n}\n\nfunction handleImageError() {\n imageFailed.value = true\n}\n</script>\n\n<template>\n <div\n data-slot=\"profile\"\n :data-size=\"props.size\"\n :data-avatar-only=\"props.avatarOnly ? '' : undefined\"\n :class=\"\n cn(\n 'inline-flex min-w-0 items-center gap-3',\n props.avatarOnly && 'gap-0',\n props.class,\n )\n \"\n >\n <span class=\"relative inline-flex shrink-0\">\n <span\n data-slot=\"profile-avatar\"\n :class=\"avatarClass()\"\n >\n <img\n v-if=\"showImage\"\n data-slot=\"profile-image\"\n :alt=\"props.alt ?? props.name ?? ''\"\n class=\"size-full object-cover\"\n :src=\"props.src\"\n @error=\"handleImageError\"\n />\n <span\n v-else\n data-slot=\"profile-fallback\"\n >\n {{ resolvedFallback }}\n </span>\n </span>\n\n <span\n v-if=\"showBadge\"\n data-slot=\"profile-badge\"\n :aria-hidden=\"!props.badgeLabel && !badgeText ? 'true' : undefined\"\n :aria-label=\"props.badgeLabel\"\n :class=\"badgeClass()\"\n >\n <span v-if=\"badgeText\">{{ badgeText }}</span>\n </span>\n </span>\n\n <span\n v-if=\"!props.avatarOnly && (props.name || props.description)\"\n data-slot=\"profile-content\"\n :class=\"contentClasses()\"\n >\n <span\n v-if=\"props.name\"\n data-slot=\"profile-name\"\n :class=\"nameClasses()\"\n :title=\"props.name\"\n >\n {{ props.name }}\n </span>\n <span\n v-if=\"props.description\"\n data-slot=\"profile-description\"\n :class=\"descriptionClasses()\"\n :title=\"props.description\"\n >\n {{ props.description }}\n </span>\n </span>\n </div>\n</template>\n",
14
+ "type": "registry:ui",
15
+ "target": "components/ui/profile/Profile.vue"
16
+ },
17
+ {
18
+ "path": "src/components/ui/profile/ProfileGroup.vue",
19
+ "content": "<script setup lang=\"ts\">\nimport { computed } from \"vue\"\nimport type { HTMLAttributes } from \"vue\"\nimport { cn } from \"@/lib/utils\"\nimport Profile from \"./Profile.vue\"\nimport type { ProfileSize } from \"./Profile.vue\"\n\nexport interface ProfileGroupItem {\n alt?: string\n class?: HTMLAttributes[\"class\"]\n fallback?: string\n name?: string\n src?: string\n}\n\nconst props = withDefaults(\n defineProps<{\n ariaLabel?: string\n class?: HTMLAttributes[\"class\"]\n items?: ProfileGroupItem[]\n limit?: number\n size?: ProfileSize\n }>(),\n {\n ariaLabel: \"Profile group\",\n limit: 4,\n size: \"default\",\n },\n)\n\nconst visibleItems = computed(() => props.items?.slice(0, props.limit) ?? [])\nconst overflowCount = computed(() =>\n Math.max((props.items?.length ?? 0) - props.limit, 0),\n)\n\nfunction itemClass(index: number, className?: HTMLAttributes[\"class\"]) {\n return cn(\n \"rounded-full ring-2 ring-background\",\n index > 0 && props.size === \"xs\" && \"-ml-2.5\",\n index > 0 && props.size === \"sm\" && \"-ml-3.5\",\n index > 0 && props.size === \"default\" && \"-ml-4\",\n index > 0 && props.size === \"lg\" && \"-ml-5\",\n index > 0 && props.size === \"xl\" && \"-ml-6\",\n className,\n )\n}\n</script>\n\n<template>\n <div\n data-slot=\"profile-group\"\n :aria-label=\"props.ariaLabel\"\n :class=\"\n cn(\n 'flex items-center [&_[data-slot=profile-badge]]:hidden [&>[data-slot=profile]]:rounded-full [&>[data-slot=profile]]:ring-2 [&>[data-slot=profile]]:ring-background',\n props.size === 'xs' &&\n '[&>[data-slot=profile]:not(:first-child)]:-ml-2.5',\n props.size === 'sm' &&\n '[&>[data-slot=profile]:not(:first-child)]:-ml-3.5',\n props.size === 'default' &&\n '[&>[data-slot=profile]:not(:first-child)]:-ml-4',\n props.size === 'lg' &&\n '[&>[data-slot=profile]:not(:first-child)]:-ml-5',\n props.size === 'xl' &&\n '[&>[data-slot=profile]:not(:first-child)]:-ml-6',\n props.class,\n )\n \"\n role=\"group\"\n >\n <template v-if=\"visibleItems.length > 0\">\n <Profile\n v-for=\"(item, index) in visibleItems\"\n :key=\"item.name ?? item.src ?? item.fallback ?? index\"\n :alt=\"item.alt\"\n avatar-only\n :class=\"itemClass(index, item.class)\"\n :fallback=\"item.fallback\"\n :name=\"item.name\"\n :size=\"props.size\"\n :src=\"item.src\"\n />\n\n <Profile\n v-if=\"overflowCount > 0\"\n :aria-label=\"`${overflowCount} more profiles`\"\n avatar-only\n :class=\"itemClass(visibleItems.length)\"\n :fallback=\"`+${overflowCount}`\"\n :size=\"props.size\"\n />\n </template>\n\n <slot v-else />\n </div>\n</template>\n",
20
+ "type": "registry:ui",
21
+ "target": "components/ui/profile/ProfileGroup.vue"
22
+ },
23
+ {
24
+ "path": "src/components/ui/profile/index.ts",
25
+ "content": "export { default as Profile } from \"./Profile.vue\"\nexport { default as ProfileGroup } from \"./ProfileGroup.vue\"\nexport type {\n ProfileBadgePlacement,\n ProfileBadgeVariant,\n ProfileSize,\n} from \"./Profile.vue\"\nexport type { ProfileGroupItem } from \"./ProfileGroup.vue\"\n",
26
+ "type": "registry:ui",
27
+ "target": "components/ui/profile/index.ts"
28
+ },
29
+ {
30
+ "path": "src/lib/utils.ts",
31
+ "content": "import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
32
+ "type": "registry:lib",
33
+ "target": "lib/utils.ts"
34
+ }
35
+ ],
36
+ "type": "registry:ui"
37
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://shadcn-vue.com/schema/registry-item.json",
3
+ "name": "progress",
4
+ "title": "Progress",
5
+ "description": "An accessible horizontal progress bar for determinate and indeterminate task state.",
6
+ "dependencies": [
7
+ "clsx",
8
+ "tailwind-merge"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "src/components/ui/progress/Progress.vue",
13
+ "content": "<script setup lang=\"ts\">\nimport { computed } from \"vue\"\nimport type { CSSProperties, HTMLAttributes } from \"vue\"\nimport { cn } from \"@/lib/utils\"\n\nexport type ProgressSize = \"sm\" | \"default\" | \"lg\"\nexport type ProgressTone = \"default\" | \"success\" | \"warning\" | \"destructive\"\nexport type ProgressValue = number | string | null | undefined\n\nexport interface ProgressValueFormatterContext {\n indeterminate: boolean\n max: number\n min: number\n percent: number\n}\n\nexport type ProgressValueFormatter = (\n value: number,\n context?: ProgressValueFormatterContext,\n) => number | string\n\nexport interface ProgressProps {\n class?: HTMLAttributes[\"class\"]\n color?: string\n indeterminate?: boolean\n label?: string\n max?: number\n min?: number\n modelValue?: ProgressValue\n showValue?: boolean\n size?: ProgressSize\n tone?: ProgressTone\n trackColor?: string\n value?: ProgressValue\n valueFormatter?: ProgressValueFormatter\n valueLabel?: string\n}\n\nconst props = withDefaults(defineProps<ProgressProps>(), {\n indeterminate: false,\n max: 100,\n min: 0,\n showValue: false,\n size: \"default\",\n tone: \"default\",\n})\n\nconst numberFormatter = computed(() =>\n new Intl.NumberFormat(undefined, {\n maximumFractionDigits: 1,\n }),\n)\n\nconst domain = computed(() => {\n let min = normalizeBoundary(props.min, 0)\n let max = normalizeBoundary(props.max, 100)\n\n if (min > max) {\n const nextMin = max\n max = min\n min = nextMin\n }\n\n if (min === max) {\n max = min + 1\n }\n\n return {\n max,\n min,\n }\n})\n\nconst rawValue = computed(() => props.modelValue ?? props.value)\nconst numericValue = computed(() => toFiniteNumber(rawValue.value))\n\nconst clampedValue = computed(() => {\n const { max, min } = domain.value\n const value = numericValue.value ?? min\n\n return Math.min(max, Math.max(min, value))\n})\n\nconst percent = computed(() => {\n const { max, min } = domain.value\n\n return ((clampedValue.value - min) / (max - min)) * 100\n})\n\nconst normalizedPercent = computed(() =>\n Math.min(100, Math.max(0, percent.value)),\n)\n\nconst valueText = computed(() => {\n if (props.valueLabel) return props.valueLabel\n if (props.indeterminate) return \"Loading\"\n\n const context = {\n indeterminate: props.indeterminate,\n max: domain.value.max,\n min: domain.value.min,\n percent: normalizedPercent.value,\n }\n\n if (props.valueFormatter) {\n return String(props.valueFormatter(clampedValue.value, context))\n }\n\n return `${numberFormatter.value.format(normalizedPercent.value)}%`\n})\n\nconst sizeClasses = computed(() => {\n if (props.size === \"sm\") {\n return {\n header: \"mb-1.5 text-xs\",\n track: \"h-1.5\",\n }\n }\n\n if (props.size === \"lg\") {\n return {\n header: \"mb-2.5 text-sm\",\n track: \"h-3\",\n }\n }\n\n return {\n header: \"mb-2 text-sm\",\n track: \"h-2\",\n }\n})\n\nconst indicatorToneClass = computed(() => {\n if (props.color) return \"\"\n\n if (props.tone === \"success\") return \"bg-[oklch(0.58_0.15_154)]\"\n if (props.tone === \"warning\") return \"bg-[oklch(0.67_0.17_68)]\"\n if (props.tone === \"destructive\") return \"bg-destructive\"\n\n return \"bg-primary\"\n})\n\nconst state = computed(() => {\n if (props.indeterminate) return \"indeterminate\"\n\n return normalizedPercent.value >= 100 ? \"complete\" : \"loading\"\n})\n\nconst hasHeader = computed(() => Boolean(props.label || props.showValue))\nconst ariaLabel = computed(() => props.label || \"Progress\")\n\nconst trackStyle = computed<CSSProperties>(() => {\n if (!props.trackColor) return {}\n\n return {\n backgroundColor: props.trackColor,\n }\n})\n\nconst indicatorStyle = computed<CSSProperties>(() => {\n const style: CSSProperties = {}\n\n if (props.color) {\n style.backgroundColor = props.color\n }\n\n if (!props.indeterminate) {\n style.transform = `scaleX(${normalizedPercent.value / 100})`\n }\n\n return style\n})\n\nfunction normalizeBoundary(value: number | undefined, fallback: number) {\n return Number.isFinite(value) ? Number(value) : fallback\n}\n\nfunction toFiniteNumber(value: ProgressValue) {\n if (value === null || value === undefined || value === \"\") return null\n\n const numberValue = typeof value === \"number\" ? value : Number(value)\n\n return Number.isFinite(numberValue) ? numberValue : null\n}\n</script>\n\n<template>\n <div data-slot=\"progress\" :class=\"cn('w-full', props.class)\">\n <div\n v-if=\"hasHeader\"\n data-slot=\"progress-header\"\n :class=\"\n cn(\n 'flex min-w-0 items-center justify-between gap-3 font-medium text-foreground',\n sizeClasses.header,\n )\n \"\n >\n <span\n v-if=\"props.label\"\n data-slot=\"progress-label\"\n class=\"min-w-0 truncate\"\n >\n {{ props.label }}\n </span>\n <span\n v-if=\"props.showValue\"\n data-slot=\"progress-value\"\n class=\"shrink-0 text-muted-foreground\"\n >\n {{ valueText }}\n </span>\n </div>\n\n <div\n data-slot=\"progress-track\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuemax=\"props.indeterminate ? undefined : domain.max\"\n :aria-valuemin=\"props.indeterminate ? undefined : domain.min\"\n :aria-valuenow=\"props.indeterminate ? undefined : clampedValue\"\n :aria-valuetext=\"valueText\"\n :class=\"\n cn(\n 'relative w-full overflow-hidden rounded-full bg-secondary',\n sizeClasses.track,\n )\n \"\n :data-state=\"state\"\n :style=\"trackStyle\"\n >\n <div\n data-slot=\"progress-indicator\"\n :class=\"\n cn(\n 'h-full w-full origin-left rounded-full transition-transform duration-300 ease-out',\n indicatorToneClass,\n )\n \"\n :data-indeterminate=\"props.indeterminate ? 'true' : undefined\"\n :data-state=\"state\"\n :style=\"indicatorStyle\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n@keyframes progress-indeterminate {\n 0% {\n transform: translateX(-110%);\n }\n\n 100% {\n transform: translateX(260%);\n }\n}\n\n[data-slot=\"progress-indicator\"][data-indeterminate=\"true\"] {\n width: 40%;\n animation: progress-indeterminate 1.25s ease-in-out infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n [data-slot=\"progress-indicator\"][data-indeterminate=\"true\"] {\n transform: translateX(75%);\n animation: none;\n opacity: 0.65;\n }\n}\n</style>\n",
14
+ "type": "registry:ui",
15
+ "target": "components/ui/progress/Progress.vue"
16
+ },
17
+ {
18
+ "path": "src/components/ui/progress/index.ts",
19
+ "content": "export { default as Progress } from \"./Progress.vue\"\nexport type {\n ProgressProps,\n ProgressSize,\n ProgressTone,\n ProgressValue,\n ProgressValueFormatter,\n ProgressValueFormatterContext,\n} from \"./Progress.vue\"\n",
20
+ "type": "registry:ui",
21
+ "target": "components/ui/progress/index.ts"
22
+ },
23
+ {
24
+ "path": "src/lib/utils.ts",
25
+ "content": "import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
26
+ "type": "registry:lib",
27
+ "target": "lib/utils.ts"
28
+ }
29
+ ],
30
+ "type": "registry:ui"
31
+ }