@vestow/vue 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 (491) hide show
  1. package/README.md +233 -0
  2. package/index.ts +8 -0
  3. package/package.json +68 -0
  4. package/src/components/accordion/Accordion.vue +45 -0
  5. package/src/components/accordion/AccordionContent.vue +31 -0
  6. package/src/components/accordion/AccordionItem.vue +26 -0
  7. package/src/components/accordion/AccordionTrigger.vue +39 -0
  8. package/src/components/accordion/index.ts +18 -0
  9. package/src/components/alert/Alert.vue +17 -0
  10. package/src/components/alert/AlertDescription.vue +12 -0
  11. package/src/components/alert/AlertTitle.vue +12 -0
  12. package/src/components/alert/index.ts +5 -0
  13. package/src/components/avatar/Avatar.vue +32 -0
  14. package/src/components/avatar/AvatarFallback.vue +23 -0
  15. package/src/components/avatar/AvatarImage.vue +18 -0
  16. package/src/components/avatar/index.ts +3 -0
  17. package/src/components/badge/Badge.vue +25 -0
  18. package/src/components/badge/index.ts +3 -0
  19. package/src/components/breadcrumb/Breadcrumb.vue +14 -0
  20. package/src/components/breadcrumb/BreadcrumbItem.vue +12 -0
  21. package/src/components/breadcrumb/BreadcrumbLink.vue +19 -0
  22. package/src/components/breadcrumb/BreadcrumbPage.vue +12 -0
  23. package/src/components/breadcrumb/BreadcrumbSeparator.vue +15 -0
  24. package/src/components/breadcrumb/index.ts +5 -0
  25. package/src/components/button/Button.vue +55 -0
  26. package/src/components/button/index.ts +3 -0
  27. package/src/components/button-group/ButtonGroup.vue +29 -0
  28. package/src/components/button-group/ButtonGroupSeparator.vue +30 -0
  29. package/src/components/button-group/ButtonGroupText.vue +29 -0
  30. package/src/components/button-group/SplitButton.vue +103 -0
  31. package/src/components/button-group/SplitButtonItems.vue +50 -0
  32. package/src/components/button-group/index.ts +34 -0
  33. package/src/components/calendar/Calendar.vue +120 -0
  34. package/src/components/calendar/RangeCalendar.vue +127 -0
  35. package/src/components/calendar/index.ts +2 -0
  36. package/src/components/card/Card.vue +12 -0
  37. package/src/components/card/CardAction.vue +12 -0
  38. package/src/components/card/CardContent.vue +12 -0
  39. package/src/components/card/CardDescription.vue +12 -0
  40. package/src/components/card/CardFooter.vue +12 -0
  41. package/src/components/card/CardHeader.vue +15 -0
  42. package/src/components/card/CardTitle.vue +12 -0
  43. package/src/components/card/index.ts +7 -0
  44. package/src/components/carousel/Carousel.vue +164 -0
  45. package/src/components/carousel/CarouselContent.vue +43 -0
  46. package/src/components/carousel/CarouselDots.vue +42 -0
  47. package/src/components/carousel/CarouselItem.vue +58 -0
  48. package/src/components/carousel/CarouselNext.vue +45 -0
  49. package/src/components/carousel/CarouselPrevious.vue +45 -0
  50. package/src/components/carousel/index.ts +44 -0
  51. package/src/components/cascade-select/CascadeSelect.vue +314 -0
  52. package/src/components/cascade-select/index.ts +11 -0
  53. package/src/components/chart/AreaChart.vue +201 -0
  54. package/src/components/chart/BarChart.vue +389 -0
  55. package/src/components/chart/ChartContainer.vue +127 -0
  56. package/src/components/chart/ChartCrosshair.vue +92 -0
  57. package/src/components/chart/ChartLegend.vue +63 -0
  58. package/src/components/chart/ChartTooltipCard.vue +49 -0
  59. package/src/components/chart/LineChart.vue +214 -0
  60. package/src/components/chart/PieChart.vue +280 -0
  61. package/src/components/chart/RadarChart.vue +291 -0
  62. package/src/components/chart/RadialChart.vue +354 -0
  63. package/src/components/chart/index.ts +30 -0
  64. package/src/components/chart/polar.ts +5 -0
  65. package/src/components/chart/tooltip.ts +5 -0
  66. package/src/components/chart/types.ts +52 -0
  67. package/src/components/chart/useChartSeries.ts +138 -0
  68. package/src/components/chart/xy-label.ts +5 -0
  69. package/src/components/checkbox/Checkbox.vue +81 -0
  70. package/src/components/checkbox/CheckboxField.vue +129 -0
  71. package/src/components/checkbox/CheckboxGroup.vue +62 -0
  72. package/src/components/checkbox/index.ts +21 -0
  73. package/src/components/chip/Chip.vue +73 -0
  74. package/src/components/chip/index.ts +3 -0
  75. package/src/components/code-block/CodeBlock.vue +100 -0
  76. package/src/components/code-block/index.ts +4 -0
  77. package/src/components/collapsible/Collapsible.vue +15 -0
  78. package/src/components/collapsible/CollapsibleContent.vue +26 -0
  79. package/src/components/collapsible/CollapsibleTrigger.vue +12 -0
  80. package/src/components/collapsible/index.ts +3 -0
  81. package/src/components/combobox/Combobox.vue +23 -0
  82. package/src/components/combobox/ComboboxAnchor.vue +20 -0
  83. package/src/components/combobox/ComboboxEmpty.vue +21 -0
  84. package/src/components/combobox/ComboboxGroup.vue +23 -0
  85. package/src/components/combobox/ComboboxInput.vue +32 -0
  86. package/src/components/combobox/ComboboxItem.vue +38 -0
  87. package/src/components/combobox/ComboboxList.vue +43 -0
  88. package/src/components/combobox/ComboboxSeparator.vue +18 -0
  89. package/src/components/combobox/ComboboxTrigger.vue +12 -0
  90. package/src/components/combobox/index.ts +9 -0
  91. package/src/components/command/Command.vue +54 -0
  92. package/src/components/command/CommandDialog.vue +41 -0
  93. package/src/components/command/CommandEmpty.vue +19 -0
  94. package/src/components/command/CommandGroup.vue +28 -0
  95. package/src/components/command/CommandInput.vue +25 -0
  96. package/src/components/command/CommandItem.vue +40 -0
  97. package/src/components/command/CommandList.vue +13 -0
  98. package/src/components/command/CommandSeparator.vue +11 -0
  99. package/src/components/command/CommandShortcut.vue +13 -0
  100. package/src/components/command/index.ts +34 -0
  101. package/src/components/command-block/CommandBlock.vue +90 -0
  102. package/src/components/command-block/index.ts +2 -0
  103. package/src/components/confirm-dialog/ConfirmDialog.vue +37 -0
  104. package/src/components/confirm-dialog/index.ts +1 -0
  105. package/src/components/confirm-popup/ConfirmPopup.vue +123 -0
  106. package/src/components/confirm-popup/index.ts +1 -0
  107. package/src/components/context-menu/ContextMenu.vue +15 -0
  108. package/src/components/context-menu/ContextMenuCheckboxItem.vue +30 -0
  109. package/src/components/context-menu/ContextMenuContent.vue +36 -0
  110. package/src/components/context-menu/ContextMenuGroup.vue +12 -0
  111. package/src/components/context-menu/ContextMenuItem.vue +32 -0
  112. package/src/components/context-menu/ContextMenuLabel.vue +21 -0
  113. package/src/components/context-menu/ContextMenuRadioGroup.vue +15 -0
  114. package/src/components/context-menu/ContextMenuRadioItem.vue +30 -0
  115. package/src/components/context-menu/ContextMenuSeparator.vue +19 -0
  116. package/src/components/context-menu/ContextMenuShortcut.vue +13 -0
  117. package/src/components/context-menu/ContextMenuSub.vue +15 -0
  118. package/src/components/context-menu/ContextMenuSubContent.vue +26 -0
  119. package/src/components/context-menu/ContextMenuSubTrigger.vue +26 -0
  120. package/src/components/context-menu/ContextMenuTrigger.vue +12 -0
  121. package/src/components/context-menu/index.ts +14 -0
  122. package/src/components/data-table/DataTable.vue +458 -0
  123. package/src/components/data-table/DataTableFacetedFilter.vue +97 -0
  124. package/src/components/data-table/DataTablePagination.vue +103 -0
  125. package/src/components/data-table/DataTableViewOptions.vue +69 -0
  126. package/src/components/data-table/features.ts +87 -0
  127. package/src/components/data-table/index.ts +27 -0
  128. package/src/components/data-table/pagination-adapter.ts +67 -0
  129. package/src/components/data-table/selection-column.ts +48 -0
  130. package/src/components/data-table/types.ts +36 -0
  131. package/src/components/data-view/DataView.vue +136 -0
  132. package/src/components/data-view/index.ts +1 -0
  133. package/src/components/date-picker/DatePicker.vue +117 -0
  134. package/src/components/date-picker/DateRangePicker.vue +122 -0
  135. package/src/components/date-picker/index.ts +2 -0
  136. package/src/components/deferred/Deferred.vue +80 -0
  137. package/src/components/deferred/index.ts +1 -0
  138. package/src/components/dialog/Dialog.vue +15 -0
  139. package/src/components/dialog/DialogClose.vue +12 -0
  140. package/src/components/dialog/DialogContent.vue +46 -0
  141. package/src/components/dialog/DialogDescription.vue +19 -0
  142. package/src/components/dialog/DialogFooter.vue +12 -0
  143. package/src/components/dialog/DialogHeader.vue +12 -0
  144. package/src/components/dialog/DialogTitle.vue +19 -0
  145. package/src/components/dialog/DialogTrigger.vue +12 -0
  146. package/src/components/dialog/index.ts +10 -0
  147. package/src/components/doc-example/DocExample.vue +41 -0
  148. package/src/components/doc-example/index.ts +1 -0
  149. package/src/components/doc-text/DocText.vue +64 -0
  150. package/src/components/doc-text/index.ts +1 -0
  151. package/src/components/dropdown-menu/DropdownMenu.vue +15 -0
  152. package/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue +33 -0
  153. package/src/components/dropdown-menu/DropdownMenuContent.vue +36 -0
  154. package/src/components/dropdown-menu/DropdownMenuGroup.vue +12 -0
  155. package/src/components/dropdown-menu/DropdownMenuItem.vue +32 -0
  156. package/src/components/dropdown-menu/DropdownMenuLabel.vue +24 -0
  157. package/src/components/dropdown-menu/DropdownMenuRadioGroup.vue +15 -0
  158. package/src/components/dropdown-menu/DropdownMenuRadioItem.vue +33 -0
  159. package/src/components/dropdown-menu/DropdownMenuSeparator.vue +19 -0
  160. package/src/components/dropdown-menu/DropdownMenuShortcut.vue +13 -0
  161. package/src/components/dropdown-menu/DropdownMenuSub.vue +15 -0
  162. package/src/components/dropdown-menu/DropdownMenuSubContent.vue +29 -0
  163. package/src/components/dropdown-menu/DropdownMenuSubTrigger.vue +26 -0
  164. package/src/components/dropdown-menu/DropdownMenuTrigger.vue +12 -0
  165. package/src/components/dropdown-menu/index.ts +14 -0
  166. package/src/components/editable/Editable.vue +41 -0
  167. package/src/components/editable/EditableArea.vue +22 -0
  168. package/src/components/editable/EditableCancelTrigger.vue +40 -0
  169. package/src/components/editable/EditableEditTrigger.vue +40 -0
  170. package/src/components/editable/EditableInput.vue +28 -0
  171. package/src/components/editable/EditablePreview.vue +34 -0
  172. package/src/components/editable/EditableSubmitTrigger.vue +40 -0
  173. package/src/components/editable/index.ts +17 -0
  174. package/src/components/empty/Empty.vue +17 -0
  175. package/src/components/empty/EmptyActions.vue +14 -0
  176. package/src/components/empty/EmptyDescription.vue +12 -0
  177. package/src/components/empty/EmptyMedia.vue +16 -0
  178. package/src/components/empty/EmptyTitle.vue +17 -0
  179. package/src/components/empty/index.ts +7 -0
  180. package/src/components/field/Field.vue +22 -0
  181. package/src/components/field/FieldDescription.vue +20 -0
  182. package/src/components/field/FieldGroup.vue +22 -0
  183. package/src/components/field/FieldLabel.vue +27 -0
  184. package/src/components/field/FieldSeparator.vue +28 -0
  185. package/src/components/field/index.ts +7 -0
  186. package/src/components/fieldset/Fieldset.vue +126 -0
  187. package/src/components/fieldset/index.ts +1 -0
  188. package/src/components/file-upload/FileUpload.vue +149 -0
  189. package/src/components/file-upload/index.ts +8 -0
  190. package/src/components/float-label/FloatLabel.vue +26 -0
  191. package/src/components/float-label/index.ts +3 -0
  192. package/src/components/form/Form.vue +126 -0
  193. package/src/components/form/FormDescription.vue +12 -0
  194. package/src/components/form/FormField.vue +127 -0
  195. package/src/components/form/FormItem.vue +12 -0
  196. package/src/components/form/FormLabel.vue +14 -0
  197. package/src/components/form/FormMessage.vue +31 -0
  198. package/src/components/form/context.ts +54 -0
  199. package/src/components/form/errors.ts +6 -0
  200. package/src/components/form/index.ts +7 -0
  201. package/src/components/form/types.ts +55 -0
  202. package/src/components/hover-card/HoverCard.vue +27 -0
  203. package/src/components/hover-card/HoverCardContent.vue +36 -0
  204. package/src/components/hover-card/HoverCardTrigger.vue +12 -0
  205. package/src/components/hover-card/index.ts +3 -0
  206. package/src/components/ifta-label/IftaLabel.vue +26 -0
  207. package/src/components/ifta-label/index.ts +1 -0
  208. package/src/components/index.ts +89 -0
  209. package/src/components/input/Input.vue +87 -0
  210. package/src/components/input/index.ts +1 -0
  211. package/src/components/input-color/ColorArea.vue +36 -0
  212. package/src/components/input-color/ColorField.vue +32 -0
  213. package/src/components/input-color/ColorSlider.vue +31 -0
  214. package/src/components/input-color/InputColor.vue +65 -0
  215. package/src/components/input-color/index.ts +16 -0
  216. package/src/components/input-group/InputGroup.vue +26 -0
  217. package/src/components/input-group/InputGroupAddon.vue +32 -0
  218. package/src/components/input-group/InputGroupInput.vue +33 -0
  219. package/src/components/input-group/index.ts +17 -0
  220. package/src/components/input-number/InputNumber.vue +82 -0
  221. package/src/components/input-number/index.ts +1 -0
  222. package/src/components/input-otp/InputOtp.vue +186 -0
  223. package/src/components/input-otp/index.ts +1 -0
  224. package/src/components/input-password/InputPassword.vue +116 -0
  225. package/src/components/input-password/index.ts +5 -0
  226. package/src/components/input-tags/InputTags.vue +38 -0
  227. package/src/components/input-tags/InputTagsClear.vue +39 -0
  228. package/src/components/input-tags/InputTagsInput.vue +27 -0
  229. package/src/components/input-tags/InputTagsItem.vue +40 -0
  230. package/src/components/input-tags/InputTagsItemDelete.vue +32 -0
  231. package/src/components/input-tags/InputTagsItemText.vue +18 -0
  232. package/src/components/input-tags/index.ts +16 -0
  233. package/src/components/kbd/Kbd.vue +17 -0
  234. package/src/components/kbd/KbdGroup.vue +15 -0
  235. package/src/components/kbd/index.ts +4 -0
  236. package/src/components/label/Label.vue +23 -0
  237. package/src/components/label/index.ts +1 -0
  238. package/src/components/listbox/Listbox.vue +42 -0
  239. package/src/components/listbox/ListboxContent.vue +22 -0
  240. package/src/components/listbox/ListboxFilter.vue +34 -0
  241. package/src/components/listbox/ListboxGroup.vue +31 -0
  242. package/src/components/listbox/ListboxItem.vue +46 -0
  243. package/src/components/listbox/index.ts +19 -0
  244. package/src/components/mask/Mask.vue +205 -0
  245. package/src/components/mask/index.ts +15 -0
  246. package/src/components/menubar/Menubar.vue +26 -0
  247. package/src/components/menubar/MenubarCheckboxItem.vue +30 -0
  248. package/src/components/menubar/MenubarContent.vue +52 -0
  249. package/src/components/menubar/MenubarGroup.vue +12 -0
  250. package/src/components/menubar/MenubarItem.vue +32 -0
  251. package/src/components/menubar/MenubarLabel.vue +21 -0
  252. package/src/components/menubar/MenubarMenu.vue +12 -0
  253. package/src/components/menubar/MenubarRadioGroup.vue +15 -0
  254. package/src/components/menubar/MenubarRadioItem.vue +30 -0
  255. package/src/components/menubar/MenubarSeparator.vue +12 -0
  256. package/src/components/menubar/MenubarShortcut.vue +13 -0
  257. package/src/components/menubar/MenubarSub.vue +15 -0
  258. package/src/components/menubar/MenubarSubContent.vue +26 -0
  259. package/src/components/menubar/MenubarSubTrigger.vue +26 -0
  260. package/src/components/menubar/MenubarTrigger.vue +30 -0
  261. package/src/components/menubar/index.ts +29 -0
  262. package/src/components/navigation-menu/NavigationMenu.vue +43 -0
  263. package/src/components/navigation-menu/NavigationMenuContent.vue +63 -0
  264. package/src/components/navigation-menu/NavigationMenuIndicator.vue +31 -0
  265. package/src/components/navigation-menu/NavigationMenuItem.vue +20 -0
  266. package/src/components/navigation-menu/NavigationMenuLink.vue +34 -0
  267. package/src/components/navigation-menu/NavigationMenuList.vue +23 -0
  268. package/src/components/navigation-menu/NavigationMenuTrigger.vue +38 -0
  269. package/src/components/navigation-menu/NavigationMenuViewport.vue +34 -0
  270. package/src/components/navigation-menu/index.ts +18 -0
  271. package/src/components/order-list/OrderList.vue +168 -0
  272. package/src/components/order-list/SelectableList.vue +200 -0
  273. package/src/components/order-list/index.ts +1 -0
  274. package/src/components/pagination/Pagination.vue +133 -0
  275. package/src/components/pagination/index.ts +1 -0
  276. package/src/components/panel/Panel.vue +69 -0
  277. package/src/components/panel/index.ts +1 -0
  278. package/src/components/pick-list/PickList.vue +211 -0
  279. package/src/components/pick-list/index.ts +1 -0
  280. package/src/components/popover/Popover.vue +15 -0
  281. package/src/components/popover/PopoverAnchor.vue +12 -0
  282. package/src/components/popover/PopoverContent.vue +39 -0
  283. package/src/components/popover/PopoverTrigger.vue +12 -0
  284. package/src/components/popover/index.ts +4 -0
  285. package/src/components/progress/Progress.vue +39 -0
  286. package/src/components/progress/index.ts +1 -0
  287. package/src/components/props-table/PropsTable.vue +62 -0
  288. package/src/components/props-table/index.ts +2 -0
  289. package/src/components/radio-group/RadioGroup.vue +52 -0
  290. package/src/components/radio-group/RadioGroupItem.vue +80 -0
  291. package/src/components/radio-group/RadioGroupItemField.vue +128 -0
  292. package/src/components/radio-group/index.ts +21 -0
  293. package/src/components/rating/Rating.vue +70 -0
  294. package/src/components/rating/RatingItem.vue +26 -0
  295. package/src/components/rating/RatingItemIndicator.vue +28 -0
  296. package/src/components/rating/RatingStar.vue +16 -0
  297. package/src/components/rating/index.ts +13 -0
  298. package/src/components/scroll-area/ScrollArea.vue +52 -0
  299. package/src/components/scroll-area/index.ts +1 -0
  300. package/src/components/search-input/SearchInput.vue +46 -0
  301. package/src/components/search-input/index.ts +1 -0
  302. package/src/components/select/Select.vue +15 -0
  303. package/src/components/select/SelectContent.vue +67 -0
  304. package/src/components/select/SelectGroup.vue +20 -0
  305. package/src/components/select/SelectItem.vue +59 -0
  306. package/src/components/select/SelectLabel.vue +20 -0
  307. package/src/components/select/SelectSeparator.vue +18 -0
  308. package/src/components/select/SelectTrigger.vue +101 -0
  309. package/src/components/select/SelectValue.vue +46 -0
  310. package/src/components/select/index.ts +8 -0
  311. package/src/components/separator/Separator.vue +25 -0
  312. package/src/components/separator/index.ts +1 -0
  313. package/src/components/sheet/Sheet.vue +15 -0
  314. package/src/components/sheet/SheetClose.vue +12 -0
  315. package/src/components/sheet/SheetContent.vue +45 -0
  316. package/src/components/sheet/SheetDescription.vue +19 -0
  317. package/src/components/sheet/SheetFooter.vue +12 -0
  318. package/src/components/sheet/SheetHeader.vue +12 -0
  319. package/src/components/sheet/SheetTitle.vue +19 -0
  320. package/src/components/sheet/SheetTrigger.vue +12 -0
  321. package/src/components/sheet/index.ts +10 -0
  322. package/src/components/sidebar/Sidebar.vue +108 -0
  323. package/src/components/sidebar/SidebarContent.vue +19 -0
  324. package/src/components/sidebar/SidebarFooter.vue +19 -0
  325. package/src/components/sidebar/SidebarGroup.vue +19 -0
  326. package/src/components/sidebar/SidebarGroupAction.vue +28 -0
  327. package/src/components/sidebar/SidebarGroupContent.vue +19 -0
  328. package/src/components/sidebar/SidebarGroupLabel.vue +25 -0
  329. package/src/components/sidebar/SidebarHeader.vue +19 -0
  330. package/src/components/sidebar/SidebarInput.vue +15 -0
  331. package/src/components/sidebar/SidebarInset.vue +22 -0
  332. package/src/components/sidebar/SidebarMenu.vue +19 -0
  333. package/src/components/sidebar/SidebarMenuAction.vue +41 -0
  334. package/src/components/sidebar/SidebarMenuBadge.vue +24 -0
  335. package/src/components/sidebar/SidebarMenuButton.vue +94 -0
  336. package/src/components/sidebar/SidebarMenuItem.vue +19 -0
  337. package/src/components/sidebar/SidebarMenuSkeleton.vue +36 -0
  338. package/src/components/sidebar/SidebarMenuSub.vue +22 -0
  339. package/src/components/sidebar/SidebarMenuSubButton.vue +39 -0
  340. package/src/components/sidebar/SidebarMenuSubItem.vue +19 -0
  341. package/src/components/sidebar/SidebarProvider.vue +114 -0
  342. package/src/components/sidebar/SidebarRail.vue +37 -0
  343. package/src/components/sidebar/SidebarSeparator.vue +15 -0
  344. package/src/components/sidebar/SidebarTrigger.vue +27 -0
  345. package/src/components/sidebar/context.ts +39 -0
  346. package/src/components/sidebar/index.ts +34 -0
  347. package/src/components/skeleton/Skeleton.vue +10 -0
  348. package/src/components/skeleton/index.ts +1 -0
  349. package/src/components/skip-link/SkipLink.vue +45 -0
  350. package/src/components/skip-link/index.ts +1 -0
  351. package/src/components/slider/Slider.vue +57 -0
  352. package/src/components/slider/index.ts +3 -0
  353. package/src/components/speed-dial/SpeedDial.vue +362 -0
  354. package/src/components/speed-dial/index.ts +28 -0
  355. package/src/components/spinner/Spinner.vue +20 -0
  356. package/src/components/spinner/index.ts +1 -0
  357. package/src/components/splitter/Splitter.vue +24 -0
  358. package/src/components/splitter/SplitterHandle.vue +51 -0
  359. package/src/components/splitter/SplitterPanel.vue +30 -0
  360. package/src/components/splitter/index.ts +14 -0
  361. package/src/components/stepper/Stepper.vue +34 -0
  362. package/src/components/stepper/StepperItem.vue +113 -0
  363. package/src/components/stepper/index.ts +2 -0
  364. package/src/components/switch/Switch.vue +35 -0
  365. package/src/components/switch/index.ts +1 -0
  366. package/src/components/table/Table.vue +24 -0
  367. package/src/components/table/TableBody.vue +12 -0
  368. package/src/components/table/TableCell.vue +12 -0
  369. package/src/components/table/TableEmpty.vue +20 -0
  370. package/src/components/table/TableHead.vue +17 -0
  371. package/src/components/table/TableHeader.vue +12 -0
  372. package/src/components/table/TableRow.vue +19 -0
  373. package/src/components/table/index.ts +7 -0
  374. package/src/components/tabs/Tabs.vue +23 -0
  375. package/src/components/tabs/TabsContent.vue +23 -0
  376. package/src/components/tabs/TabsList.vue +26 -0
  377. package/src/components/tabs/TabsTrigger.vue +30 -0
  378. package/src/components/tabs/index.ts +4 -0
  379. package/src/components/textarea/Textarea.vue +25 -0
  380. package/src/components/textarea/index.ts +1 -0
  381. package/src/components/theme-controls/LocaleMenu.vue +95 -0
  382. package/src/components/theme-controls/PaletteMenu.vue +155 -0
  383. package/src/components/theme-controls/ThemeToggle.vue +21 -0
  384. package/src/components/theme-controls/index.ts +15 -0
  385. package/src/components/timeline/Timeline.vue +20 -0
  386. package/src/components/timeline/TimelineItem.vue +68 -0
  387. package/src/components/timeline/index.ts +15 -0
  388. package/src/components/toast/Toaster.vue +62 -0
  389. package/src/components/toast/index.ts +4 -0
  390. package/src/components/toast/toast.ts +57 -0
  391. package/src/components/toggle/Toggle.vue +32 -0
  392. package/src/components/toggle/ToggleGroup.vue +56 -0
  393. package/src/components/toggle/ToggleGroupItem.vue +33 -0
  394. package/src/components/toggle/index.ts +18 -0
  395. package/src/components/token-table/TokenTable.vue +67 -0
  396. package/src/components/token-table/index.ts +2 -0
  397. package/src/components/toolbar/Toolbar.vue +34 -0
  398. package/src/components/toolbar/ToolbarButton.vue +33 -0
  399. package/src/components/toolbar/ToolbarSeparator.vue +21 -0
  400. package/src/components/toolbar/index.ts +3 -0
  401. package/src/components/tooltip/Tooltip.vue +15 -0
  402. package/src/components/tooltip/TooltipContent.vue +38 -0
  403. package/src/components/tooltip/TooltipProvider.vue +16 -0
  404. package/src/components/tooltip/TooltipTrigger.vue +12 -0
  405. package/src/components/tooltip/index.ts +4 -0
  406. package/src/components/tree/Tree.vue +53 -0
  407. package/src/components/tree/TreeItem.vue +59 -0
  408. package/src/components/tree/index.ts +21 -0
  409. package/src/components/tree-select/TreeSelect.vue +141 -0
  410. package/src/components/tree-select/index.ts +1 -0
  411. package/src/components/tree-table/TreeTable.vue +302 -0
  412. package/src/components/tree-table/features.ts +49 -0
  413. package/src/components/tree-table/index.ts +3 -0
  414. package/src/components/video-player/VideoPlayer.vue +472 -0
  415. package/src/components/video-player/index.ts +20 -0
  416. package/src/composables/index.ts +15 -0
  417. package/src/composables/useBase.ts +32 -0
  418. package/src/composables/useChartPalette.ts +33 -0
  419. package/src/composables/useColorMode.ts +29 -0
  420. package/src/composables/useConfirm.ts +81 -0
  421. package/src/composables/useDelayedFlag.ts +62 -0
  422. package/src/composables/useI18n.ts +107 -0
  423. package/src/composables/useIsMobile.ts +34 -0
  424. package/src/composables/useMenuAccent.ts +32 -0
  425. package/src/composables/useMenuAppearance.ts +31 -0
  426. package/src/composables/useMenuColor.ts +31 -0
  427. package/src/composables/usePalette.ts +30 -0
  428. package/src/composables/useStyle.ts +35 -0
  429. package/src/composables/useSurface.ts +30 -0
  430. package/src/composables/useTableQuery.ts +73 -0
  431. package/src/composables/useThemeController.ts +48 -0
  432. package/src/i18n/README.md +68 -0
  433. package/src/i18n/controller.ts +233 -0
  434. package/src/i18n/dictionary.ts +43 -0
  435. package/src/i18n/index.ts +34 -0
  436. package/src/i18n/registry.ts +64 -0
  437. package/src/i18n/ui/en/ui.json +114 -0
  438. package/src/i18n/ui/en/zod.json +16 -0
  439. package/src/i18n/ui/index.ts +48 -0
  440. package/src/i18n/ui/vi/ui.json +114 -0
  441. package/src/i18n/ui/vi/zod.json +16 -0
  442. package/src/lib/date.ts +24 -0
  443. package/src/lib/focus.ts +12 -0
  444. package/src/lib/icons.ts +345 -0
  445. package/src/lib/menu-styles.ts +16 -0
  446. package/src/lib/menu.ts +20 -0
  447. package/src/lib/platform.ts +5 -0
  448. package/src/lib/types.ts +6 -0
  449. package/src/lib/utils.ts +9 -0
  450. package/src/lib/zod-messages.ts +127 -0
  451. package/src/styles/chart.css +30 -0
  452. package/src/styles/index.css +18 -0
  453. package/src/variants/README.md +55 -0
  454. package/src/variants/components/accordion.ts +71 -0
  455. package/src/variants/components/alert.ts +20 -0
  456. package/src/variants/components/badge.ts +76 -0
  457. package/src/variants/components/button-group.ts +136 -0
  458. package/src/variants/components/button.ts +160 -0
  459. package/src/variants/components/checkbox.ts +67 -0
  460. package/src/variants/components/chip.ts +51 -0
  461. package/src/variants/components/code-block.ts +22 -0
  462. package/src/variants/components/dialog.ts +28 -0
  463. package/src/variants/components/empty.ts +60 -0
  464. package/src/variants/components/field.ts +35 -0
  465. package/src/variants/components/float-label.ts +95 -0
  466. package/src/variants/components/input-group.ts +73 -0
  467. package/src/variants/components/input-password.ts +68 -0
  468. package/src/variants/components/kbd.ts +47 -0
  469. package/src/variants/components/picker-trigger.ts +30 -0
  470. package/src/variants/components/radio-group.ts +63 -0
  471. package/src/variants/components/sheet.ts +23 -0
  472. package/src/variants/components/sidebar.ts +33 -0
  473. package/src/variants/components/slider.ts +49 -0
  474. package/src/variants/components/timeline.ts +45 -0
  475. package/src/variants/components/toggle.ts +58 -0
  476. package/src/variants/index.ts +35 -0
  477. package/src/variants/lib/chart/polar.ts +139 -0
  478. package/src/variants/lib/chart/tooltip.ts +101 -0
  479. package/src/variants/lib/chart/types.ts +172 -0
  480. package/src/variants/lib/chart/xy-label.ts +42 -0
  481. package/src/variants/lib/focus.ts +66 -0
  482. package/src/variants/lib/form-errors.ts +59 -0
  483. package/src/variants/lib/highlight.ts +548 -0
  484. package/src/variants/lib/list-move.ts +63 -0
  485. package/src/variants/lib/mask.ts +106 -0
  486. package/src/variants/lib/media.ts +56 -0
  487. package/src/variants/lib/menu-styles.ts +71 -0
  488. package/src/variants/lib/platform.ts +68 -0
  489. package/src/variants/lib/tree.ts +119 -0
  490. package/src/variants/lib/upload.ts +58 -0
  491. package/src/variants/lib/utils.ts +11 -0
@@ -0,0 +1,94 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from 'reka-ui'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import type { SidebarMenuButtonVariants } from './index'
5
+ import { Primitive } from 'reka-ui'
6
+ import { computed } from 'vue'
7
+ import { cn } from '../../lib/utils'
8
+ import Tooltip from '../tooltip/Tooltip.vue'
9
+ import TooltipContent from '../tooltip/TooltipContent.vue'
10
+ import TooltipTrigger from '../tooltip/TooltipTrigger.vue'
11
+ import { useSidebar } from './context'
12
+ import { sidebarMenuButtonVariants } from './index'
13
+
14
+ /**
15
+ * Gốc của component là một provider KHÔNG vẽ ra DOM, nên thuộc tính rơi tự do
16
+ * không có chỗ đáp và biến mất hẳn. Đo được: đặt `id` lên component thì nó
17
+ * không xuất hiện ở bất kỳ đâu trong DOM, và `<Label for>` trỏ vào hư không.
18
+ *
19
+ * Chuyển tay xuống CẢ HAI nhánh: nhánh không có tooltip vốn đang nhận attrs
20
+ * nhờ fallthrough, bật `inheritAttrs: false` mà quên nó là lấy mất.
21
+ */
22
+ defineOptions({ inheritAttrs: false })
23
+
24
+ const props = withDefaults(
25
+ defineProps<PrimitiveProps & ClassProps & {
26
+ isActive?: boolean
27
+ variant?: SidebarMenuButtonVariants['variant']
28
+ size?: SidebarMenuButtonVariants['size']
29
+ /** Nhãn hiện khi sidebar đã thu về cỡ icon. Bỏ trống thì không có tooltip. */
30
+ tooltip?: string
31
+ /**
32
+ * Hiện tooltip cả khi cột đang mở.
33
+ *
34
+ * Dành cho cột `collapsible="none"` rộng đúng cỡ icon — nó không bao giờ ở
35
+ * trạng thái `collapsed` nên luật mặc định sẽ giấu tooltip vĩnh viễn, trong
36
+ * khi nhãn thì vẫn bị cắt mất.
37
+ */
38
+ alwaysShowTooltip?: boolean
39
+ }>(),
40
+ { as: 'button', isActive: false, variant: 'default', size: 'default', alwaysShowTooltip: false },
41
+ )
42
+
43
+ const { isMobile, state } = useSidebar()
44
+
45
+ const nativeType = computed(() => (props.as === 'button' ? 'button' : undefined))
46
+ const buttonClass = computed(() => cn(sidebarMenuButtonVariants({ variant: props.variant, size: props.size }), props.class))
47
+ </script>
48
+
49
+ <template>
50
+ <!--
51
+ Tooltip chỉ có nghĩa khi nhãn đã bị thu mất. Ở trạng thái mở, hoặc trên
52
+ mobile (sidebar là ngăn kéo, luôn hiện đủ chữ), nó lặp lại đúng thứ đang
53
+ đọc được — và trình đọc màn hình sẽ đọc hai lần.
54
+ -->
55
+ <Tooltip v-if="tooltip">
56
+ <TooltipTrigger as-child>
57
+ <Primitive
58
+ v-bind="$attrs"
59
+ :as="as"
60
+ :as-child="asChild"
61
+ :type="nativeType"
62
+ data-slot="sidebar-menu-button"
63
+ data-sidebar="menu-button"
64
+ :data-size="size"
65
+ :data-active="isActive"
66
+ :class="buttonClass"
67
+ >
68
+ <slot />
69
+ </Primitive>
70
+ </TooltipTrigger>
71
+ <TooltipContent
72
+ v-if="alwaysShowTooltip || (state === 'collapsed' && !isMobile)"
73
+ side="right"
74
+ align="center"
75
+ >
76
+ {{ tooltip }}
77
+ </TooltipContent>
78
+ </Tooltip>
79
+
80
+ <Primitive
81
+ v-else
82
+ v-bind="$attrs"
83
+ :as="as"
84
+ :as-child="asChild"
85
+ :type="nativeType"
86
+ data-slot="sidebar-menu-button"
87
+ data-sidebar="menu-button"
88
+ :data-size="size"
89
+ :data-active="isActive"
90
+ :class="buttonClass"
91
+ >
92
+ <slot />
93
+ </Primitive>
94
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { cn } from '../../lib/utils'
4
+
5
+ const props = defineProps<ClassProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <li
10
+ data-slot="sidebar-menu-item"
11
+ data-sidebar="menu-item"
12
+ :class="cn(
13
+ 'group/menu-item relative',
14
+ props.class,
15
+ )"
16
+ >
17
+ <slot />
18
+ </li>
19
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import type { CSSProperties } from 'vue'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import { computed } from 'vue'
5
+ import { cn } from '../../lib/utils'
6
+ import Skeleton from '../skeleton/Skeleton.vue'
7
+
8
+ const props = withDefaults(
9
+ defineProps<ClassProps & { showIcon?: boolean }>(),
10
+ { showIcon: false },
11
+ )
12
+
13
+ /**
14
+ * Bề rộng ngẫu nhiên 50–90%.
15
+ *
16
+ * Tính một lần ở setup chứ không trong render: đọc `Math.random()` mỗi lần vẽ
17
+ * thì mỗi lần cha cập nhật là cả danh sách nhấp nháy đổi độ dài.
18
+ */
19
+ const width = `${Math.floor(Math.random() * 40) + 50}%`
20
+ const textStyle = computed<CSSProperties>(() => ({ '--skeleton-width': width } as CSSProperties))
21
+ </script>
22
+
23
+ <template>
24
+ <div
25
+ data-slot="sidebar-menu-skeleton"
26
+ data-sidebar="menu-skeleton"
27
+ :class="cn('flex h-8 items-center gap-2 rounded-md px-2', props.class)"
28
+ >
29
+ <Skeleton v-if="props.showIcon" data-sidebar="menu-skeleton-icon" class="size-4 rounded-md" />
30
+ <Skeleton
31
+ data-sidebar="menu-skeleton-text"
32
+ class="h-4 max-w-(--skeleton-width) flex-1"
33
+ :style="textStyle"
34
+ />
35
+ </div>
36
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { cn } from '../../lib/utils'
4
+
5
+ const props = defineProps<ClassProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <ul
10
+ data-slot="sidebar-menu-sub"
11
+ data-sidebar="menu-sub"
12
+ :class="cn(
13
+ [
14
+ 'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',
15
+ 'group-data-[collapsible=icon]:hidden',
16
+ ],
17
+ props.class,
18
+ )"
19
+ >
20
+ <slot />
21
+ </ul>
22
+ </template>
@@ -0,0 +1,39 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from 'reka-ui'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import { Primitive } from 'reka-ui'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const props = withDefaults(
8
+ defineProps<PrimitiveProps & ClassProps & {
9
+ isActive?: boolean
10
+ size?: 'sm' | 'md'
11
+ }>(),
12
+ { as: 'a', isActive: false, size: 'md' },
13
+ )
14
+ </script>
15
+
16
+ <template>
17
+ <Primitive
18
+ :as="as"
19
+ :as-child="asChild"
20
+ data-slot="sidebar-menu-sub-button"
21
+ data-sidebar="menu-sub-button"
22
+ :data-size="size"
23
+ :data-active="isActive"
24
+ :class="cn(
25
+ 'flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-hidden ring-sidebar-ring',
26
+ 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2',
27
+ 'active:bg-sidebar-accent active:text-sidebar-accent-foreground',
28
+ 'disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50',
29
+ '[&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground',
30
+ 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
31
+ props.size === 'sm' && 'text-xs',
32
+ props.size === 'md' && 'text-sm',
33
+ 'group-data-[collapsible=icon]:hidden',
34
+ props.class,
35
+ )"
36
+ >
37
+ <slot />
38
+ </Primitive>
39
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { cn } from '../../lib/utils'
4
+
5
+ const props = defineProps<ClassProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <li
10
+ data-slot="sidebar-menu-sub-item"
11
+ data-sidebar="menu-sub-item"
12
+ :class="cn(
13
+ 'group/menu-sub-item relative',
14
+ props.class,
15
+ )"
16
+ >
17
+ <slot />
18
+ </li>
19
+ </template>
@@ -0,0 +1,114 @@
1
+ <script setup lang="ts">
2
+ import type { CSSProperties } from 'vue'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import { computed, onBeforeUnmount, onMounted, provide, ref } from 'vue'
5
+ import { useIsMobile } from '../../composables/useIsMobile'
6
+ import { cn } from '../../lib/utils'
7
+ import TooltipProvider from '../tooltip/TooltipProvider.vue'
8
+ import {
9
+ SIDEBAR_INJECTION_KEY,
10
+ SIDEBAR_KEYBOARD_SHORTCUT,
11
+ SIDEBAR_WIDTH,
12
+ SIDEBAR_WIDTH_ICON,
13
+ } from './context'
14
+
15
+ const props = withDefaults(
16
+ defineProps<ClassProps & {
17
+ /** Trạng thái ban đầu khi không điều khiển từ ngoài. */
18
+ defaultOpen?: boolean
19
+ /**
20
+ * Điều khiển từ ngoài. Bỏ trống thì component tự giữ trạng thái.
21
+ *
22
+ * `open: undefined` trong `withDefaults` là BẮT BUỘC, không phải thừa: prop
23
+ * kiểu Boolean mà không khai default thì Vue ép giá trị vắng mặt thành
24
+ * `false` chứ không để `undefined`. Thiếu dòng đó, mọi `<SidebarProvider>`
25
+ * không truyền `open` đều bị coi là "đang được điều khiển và đang đóng" —
26
+ * sidebar dựng ra rồi nằm ngoài màn hình, không lỗi, không cảnh báo.
27
+ */
28
+ open?: boolean
29
+ style?: CSSProperties
30
+ }>(),
31
+ { defaultOpen: true, open: undefined },
32
+ )
33
+
34
+ const emit = defineEmits<{ 'update:open': [value: boolean] }>()
35
+
36
+ const isMobile = useIsMobile()
37
+ const openMobile = ref(false)
38
+
39
+ /*
40
+ * KHÔNG lưu trạng thái vào cookie như shadcn.
41
+ *
42
+ * Bên đó cookie tồn tại để `page.tsx` đọc được ở phía server và tránh nháy một
43
+ * nhịp lúc hydrate — một nhu cầu của Next.js mà repo này không có. Giữ lại thì
44
+ * nó thành một chỗ ghi mà không ai đọc, và tệ hơn: gallery block chạy 16 iframe
45
+ * cùng origin, một cookie dùng chung nghĩa là gập sidebar ở ô này thì 15 ô kia
46
+ * gập theo.
47
+ */
48
+ const internalOpen = ref(props.defaultOpen)
49
+ const isControlled = computed(() => props.open !== undefined)
50
+ const open = computed(() => (isControlled.value ? props.open! : internalOpen.value))
51
+
52
+ function setOpen(value: boolean): void {
53
+ if (!isControlled.value)
54
+ internalOpen.value = value
55
+
56
+ emit('update:open', value)
57
+ }
58
+
59
+ function setOpenMobile(value: boolean): void {
60
+ openMobile.value = value
61
+ }
62
+
63
+ function toggleSidebar(): void {
64
+ if (isMobile.value)
65
+ openMobile.value = !openMobile.value
66
+ else
67
+ setOpen(!open.value)
68
+ }
69
+
70
+ const state = computed(() => (open.value ? 'expanded' as const : 'collapsed' as const))
71
+
72
+ function onKeydown(event: KeyboardEvent): void {
73
+ if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
74
+ event.preventDefault()
75
+ toggleSidebar()
76
+ }
77
+ }
78
+
79
+ onMounted(() => window.addEventListener('keydown', onKeydown))
80
+ onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
81
+
82
+ provide(SIDEBAR_INJECTION_KEY, {
83
+ state,
84
+ open,
85
+ setOpen,
86
+ openMobile,
87
+ setOpenMobile,
88
+ isMobile,
89
+ toggleSidebar,
90
+ })
91
+
92
+ const wrapperStyle = computed<CSSProperties>(() => ({
93
+ '--sidebar-width': SIDEBAR_WIDTH,
94
+ '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
95
+ ...props.style,
96
+ } as CSSProperties))
97
+ </script>
98
+
99
+ <template>
100
+ <!-- `delayDuration: 0` — tooltip ở đây thay cho nhãn đã bị thu gọn mất, chờ
101
+ một nhịp là người dùng không biết mình đang trỏ vào mục nào. -->
102
+ <TooltipProvider :delay-duration="0">
103
+ <div
104
+ data-slot="sidebar-wrapper"
105
+ :style="wrapperStyle"
106
+ :class="cn(
107
+ 'group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar',
108
+ props.class,
109
+ )"
110
+ >
111
+ <slot />
112
+ </div>
113
+ </TooltipProvider>
114
+ </template>
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { useI18n } from '../../composables/useI18n'
4
+ import { cn } from '../../lib/utils'
5
+ import { useSidebar } from './context'
6
+
7
+ const props = defineProps<ClassProps>()
8
+
9
+ const { t } = useI18n()
10
+ const { toggleSidebar } = useSidebar()
11
+ </script>
12
+
13
+ <template>
14
+ <!-- Dải 16px sát mép sidebar: kéo/bấm để gập. `tabindex="-1"` vì đã có
15
+ `SidebarTrigger` nhận focus — hai chỗ làm cùng một việc thì bàn phím phải
16
+ Tab hai lần qua cùng một hành động. -->
17
+ <button
18
+ type="button"
19
+ data-sidebar="rail"
20
+ data-slot="sidebar-rail"
21
+ :aria-label="t('ui.sidebar.toggle')"
22
+ :title="t('ui.sidebar.toggle')"
23
+ tabindex="-1"
24
+ :class="cn(
25
+ 'absolute inset-y-0 z-(--z-elevated) hidden w-4 -translate-x-1/2 transition-all ease-linear sm:flex',
26
+ 'after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border',
27
+ 'group-data-[side=left]:-right-4 group-data-[side=right]:left-0',
28
+ 'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',
29
+ '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
30
+ 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar',
31
+ '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',
32
+ '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
33
+ props.class,
34
+ )"
35
+ @click="toggleSidebar"
36
+ />
37
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { cn } from '../../lib/utils'
4
+ import Separator from '../separator/Separator.vue'
5
+
6
+ const props = defineProps<ClassProps>()
7
+ </script>
8
+
9
+ <template>
10
+ <Separator
11
+ data-slot="sidebar-separator"
12
+ data-sidebar="separator"
13
+ :class="cn('mx-2 w-auto bg-sidebar-border', props.class)"
14
+ />
15
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { useI18n } from '../../composables/useI18n'
4
+ import { PanelLeft } from '../../lib/icons'
5
+ import { cn } from '../../lib/utils'
6
+ import Button from '../button/Button.vue'
7
+ import { useSidebar } from './context'
8
+
9
+ const props = defineProps<ClassProps>()
10
+
11
+ const { t } = useI18n()
12
+ const { toggleSidebar } = useSidebar()
13
+ </script>
14
+
15
+ <template>
16
+ <Button
17
+ data-sidebar="trigger"
18
+ data-slot="sidebar-trigger"
19
+ variant="ghost"
20
+ size="icon"
21
+ :class="cn('size-7', props.class)"
22
+ @click="toggleSidebar"
23
+ >
24
+ <PanelLeft />
25
+ <span class="sr-only">{{ t('ui.sidebar.toggle') }}</span>
26
+ </Button>
27
+ </template>
@@ -0,0 +1,39 @@
1
+ import type { ComputedRef, InjectionKey, Ref } from 'vue'
2
+ import { inject } from 'vue'
3
+
4
+ /** Bề rộng ba trạng thái. Khai ở đây để `Sidebar` và `SidebarProvider` cùng đọc. */
5
+ export const SIDEBAR_WIDTH = '16rem'
6
+ export const SIDEBAR_WIDTH_MOBILE = '18rem'
7
+ export const SIDEBAR_WIDTH_ICON = '3rem'
8
+
9
+ /** Phím tắt bật/tắt, đi kèm Cmd (macOS) hoặc Ctrl. */
10
+ export const SIDEBAR_KEYBOARD_SHORTCUT = 'b'
11
+
12
+ export interface SidebarContext {
13
+ /** `expanded` hay `collapsed` — cũng là `data-state` để CSS bắt. */
14
+ state: ComputedRef<'expanded' | 'collapsed'>
15
+ open: ComputedRef<boolean>
16
+ setOpen: (value: boolean) => void
17
+ openMobile: Ref<boolean>
18
+ setOpenMobile: (value: boolean) => void
19
+ isMobile: Readonly<Ref<boolean>>
20
+ toggleSidebar: () => void
21
+ }
22
+
23
+ export const SIDEBAR_INJECTION_KEY: InjectionKey<SidebarContext> = Symbol('woodblock-sidebar')
24
+
25
+ /**
26
+ * Đọc trạng thái sidebar từ `SidebarProvider` gần nhất.
27
+ *
28
+ * Ném lỗi thay vì trả `undefined`: mọi phần con của sidebar đều cần trạng thái
29
+ * này, thiếu provider thì chúng render ra một cái vỏ trông vẫn hợp lý nhưng
30
+ * không bấm được — đúng kiểu lỗi im lặng khó truy.
31
+ */
32
+ export function useSidebar(): SidebarContext {
33
+ const context = inject(SIDEBAR_INJECTION_KEY, null)
34
+
35
+ if (!context)
36
+ throw new Error('useSidebar phải nằm trong một <SidebarProvider>.')
37
+
38
+ return context
39
+ }
@@ -0,0 +1,34 @@
1
+ export { sidebarMenuButtonVariants, type SidebarMenuButtonVariants } from '../../variants/components/sidebar'
2
+
3
+ export {
4
+ SIDEBAR_WIDTH,
5
+ SIDEBAR_WIDTH_ICON,
6
+ SIDEBAR_WIDTH_MOBILE,
7
+ useSidebar,
8
+ } from './context'
9
+
10
+ export type { SidebarContext } from './context'
11
+ export { default as Sidebar } from './Sidebar.vue'
12
+ export { default as SidebarContent } from './SidebarContent.vue'
13
+ export { default as SidebarFooter } from './SidebarFooter.vue'
14
+ export { default as SidebarGroup } from './SidebarGroup.vue'
15
+ export { default as SidebarGroupAction } from './SidebarGroupAction.vue'
16
+ export { default as SidebarGroupContent } from './SidebarGroupContent.vue'
17
+ export { default as SidebarGroupLabel } from './SidebarGroupLabel.vue'
18
+ export { default as SidebarHeader } from './SidebarHeader.vue'
19
+ export { default as SidebarInput } from './SidebarInput.vue'
20
+ export { default as SidebarInset } from './SidebarInset.vue'
21
+ export { default as SidebarMenu } from './SidebarMenu.vue'
22
+ export { default as SidebarMenuAction } from './SidebarMenuAction.vue'
23
+ export { default as SidebarMenuBadge } from './SidebarMenuBadge.vue'
24
+ export { default as SidebarMenuButton } from './SidebarMenuButton.vue'
25
+ export { default as SidebarMenuItem } from './SidebarMenuItem.vue'
26
+ export { default as SidebarMenuSkeleton } from './SidebarMenuSkeleton.vue'
27
+ export { default as SidebarMenuSub } from './SidebarMenuSub.vue'
28
+ export { default as SidebarMenuSubButton } from './SidebarMenuSubButton.vue'
29
+ export { default as SidebarMenuSubItem } from './SidebarMenuSubItem.vue'
30
+ export { default as SidebarProvider } from './SidebarProvider.vue'
31
+ export { default as SidebarRail } from './SidebarRail.vue'
32
+ export { default as SidebarSeparator } from './SidebarSeparator.vue'
33
+
34
+ export { default as SidebarTrigger } from './SidebarTrigger.vue'
@@ -0,0 +1,10 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { cn } from '../../lib/utils'
4
+
5
+ const props = defineProps<ClassProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <div aria-hidden="true" :class="cn('animate-pulse rounded-md bg-muted', props.class)" />
10
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Skeleton } from './Skeleton.vue'
@@ -0,0 +1,45 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { useI18n } from '../../composables/useI18n'
4
+ import { focusRing } from '../../lib/focus'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const props = withDefaults(
8
+ defineProps<ClassProps & {
9
+ /** Id của vùng nội dung chính, kèm dấu `#`. */
10
+ href?: string
11
+ }>(),
12
+ { href: '#main' },
13
+ )
14
+ const { t } = useI18n()
15
+ </script>
16
+
17
+ <template>
18
+ <!--
19
+ Hai yêu cầu của một skip link, và cả hai đều dễ làm hỏng:
20
+
21
+ 1. **Vô hình cho tới khi được focus** — nhưng phải ẩn bằng `transform`, KHÔNG
22
+ phải `display:none` hay `hidden`. Hai cái đó loại phần tử khỏi chuỗi Tab
23
+ luôn, tức là cái link không bao giờ tới lượt để mà hiện ra.
24
+ `sr-only` cũng không dùng được: nó vẫn focus được nhưng lúc focus vẫn vô
25
+ hình, người dùng bàn phím sẽ thấy focus "biến mất" một nhịp.
26
+
27
+ 2. **Là phần tử focus được ĐẦU TIÊN của trang** — đặt nó ở đâu khác thì đã
28
+ phải Tab qua đúng cái đống mà nó sinh ra để bỏ qua.
29
+
30
+ Đích đến phải có `tabindex="-1"`, nếu không nhảy neo chỉ cuộn màn hình chứ
31
+ không dời focus bàn phím — người dùng bấm xong vẫn đứng nguyên chỗ cũ.
32
+ -->
33
+ <a
34
+ :href="props.href"
35
+ :class="cn(
36
+ 'absolute left-4 top-3 z-(--z-skip-link) -translate-y-[200%] rounded-md border border-border',
37
+ 'bg-background px-3 py-1.5 text-sm font-medium shadow-md transition-transform',
38
+ 'focus:translate-y-0',
39
+ focusRing,
40
+ props.class,
41
+ )"
42
+ >
43
+ <slot>{{ t('ui.skipLink') }}</slot>
44
+ </a>
45
+ </template>
@@ -0,0 +1 @@
1
+ export { default as SkipLink } from './SkipLink.vue'
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import type { SliderRootEmits, SliderRootProps } from 'reka-ui'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import type { SliderVariants } from './index'
5
+ import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui'
6
+ import { computed } from 'vue'
7
+ import { cn } from '../../lib/utils'
8
+ import { sliderThumbVariants, sliderTrackVariants } from './index'
9
+
10
+ const props = withDefaults(
11
+ defineProps<SliderRootProps & ClassProps & {
12
+ size?: SliderVariants['size']
13
+ }>(),
14
+ { size: 'md' },
15
+ )
16
+
17
+ const emits = defineEmits<SliderRootEmits>()
18
+
19
+ const delegated = computed(() => {
20
+ const { class: _class, size: _size, ...rest } = props
21
+ return rest
22
+ })
23
+
24
+ const forwarded = useForwardPropsEmits(delegated, emits)
25
+
26
+ /**
27
+ * Số núm suy ra từ giá trị, không phải một prop riêng.
28
+ *
29
+ * Khai `:model-value="[20, 60]"` là ra thanh chọn khoảng, `[20]` là thanh một
30
+ * núm — không phải nhớ bật thêm cờ `range` như PrimeVue. Đọc cả `defaultValue`
31
+ * để bản không kiểm soát cũng đúng ngay từ lần render đầu.
32
+ */
33
+ const thumbCount = computed(() => (props.modelValue ?? props.defaultValue ?? [0]).length)
34
+ </script>
35
+
36
+ <template>
37
+ <SliderRoot
38
+ v-bind="forwarded"
39
+ :class="cn(
40
+ 'relative flex touch-none select-none items-center',
41
+ 'data-[orientation=horizontal]:w-full',
42
+ 'data-[orientation=vertical]:h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col',
43
+ 'data-[disabled]:opacity-50',
44
+ props.class,
45
+ )"
46
+ >
47
+ <SliderTrack :class="sliderTrackVariants({ size: props.size })">
48
+ <SliderRange class="ui-slider-range absolute bg-slider-range data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full" />
49
+ </SliderTrack>
50
+
51
+ <SliderThumb
52
+ v-for="index in thumbCount"
53
+ :key="index"
54
+ :class="sliderThumbVariants({ size: props.size })"
55
+ />
56
+ </SliderRoot>
57
+ </template>
@@ -0,0 +1,3 @@
1
+ export { sliderThumbVariants, sliderTrackVariants, type SliderVariants } from '../../variants/components/slider'
2
+
3
+ export { default as Slider } from './Slider.vue'