@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,19 @@
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
+ // as-child để dùng chung với RouterLink mà không lồng thẻ <a> trong <a>.
8
+ const props = withDefaults(defineProps<PrimitiveProps & ClassProps>(), { as: 'a' })
9
+ </script>
10
+
11
+ <template>
12
+ <Primitive
13
+ :as="props.as"
14
+ :as-child="props.asChild"
15
+ :class="cn('rounded transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', props.class)"
16
+ >
17
+ <slot />
18
+ </Primitive>
19
+ </template>
@@ -0,0 +1,12 @@
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
+ <span role="link" aria-disabled="true" aria-current="page" :class="cn('font-medium text-foreground', props.class)">
10
+ <slot />
11
+ </span>
12
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { ChevronRight } from '../../lib/icons'
4
+ import { cn } from '../../lib/utils'
5
+
6
+ const props = defineProps<ClassProps>()
7
+ </script>
8
+
9
+ <template>
10
+ <li role="presentation" aria-hidden="true" :class="cn('[&>svg]:size-3.5', props.class)">
11
+ <slot>
12
+ <ChevronRight />
13
+ </slot>
14
+ </li>
15
+ </template>
@@ -0,0 +1,5 @@
1
+ export { default as Breadcrumb } from './Breadcrumb.vue'
2
+ export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
3
+ export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
4
+ export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
5
+ export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from 'reka-ui'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import type { ButtonVariants } from './index'
5
+ import { Primitive } from 'reka-ui'
6
+ import { computed } from 'vue'
7
+ import { LoaderCircle } from '../../lib/icons'
8
+ import { cn } from '../../lib/utils'
9
+ import { buttonVariants } from './index'
10
+
11
+ const props = withDefaults(
12
+ defineProps<PrimitiveProps & ClassProps & {
13
+ variant?: ButtonVariants['variant']
14
+ size?: ButtonVariants['size']
15
+ /** Kiểu tô: `solid` đặc, `soft` nền pha loãng, `glass` kính. */
16
+ tone?: ButtonVariants['tone']
17
+ /**
18
+ * KIỂU TÔ — `solid` · `soft` · `surface` · `outline` · `ghost`.
19
+ *
20
+ * Trục tách khỏi `variant` theo mô hình Radix Themes. `surface` là nền pha
21
+ * loãng KÈM viền, ô mà `variant="outline" tone="soft"` từng không có nghĩa.
22
+ * Xem `CLAUDE.md`, mục "Trục `fill`".
23
+ */
24
+ fill?: ButtonVariants['fill']
25
+ /** Hiện spinner và chặn tương tác. Không tự set disabled để giữ được focus. */
26
+ loading?: boolean
27
+ disabled?: boolean
28
+ }>(),
29
+ { as: 'button', loading: false, disabled: false },
30
+ )
31
+
32
+ // Khi `as` là <button> thì phải có type, nếu không trình duyệt mặc định "submit"
33
+ // và bấm nút trong form sẽ submit ngoài ý muốn.
34
+ //
35
+ // `asChild` phải loại trừ: lúc đó element thật do slot quyết định, mà `as` vẫn
36
+ // còn giá trị mặc định `'button'` — nên `<Button as-child><a/></Button>` từng ra
37
+ // `<a type="button">`, một thuộc tính vô nghĩa trên thẻ neo.
38
+ const nativeType = computed(() => (props.as === 'button' && !props.asChild ? 'button' : undefined))
39
+ </script>
40
+
41
+ <template>
42
+ <Primitive
43
+ :as="as"
44
+ :as-child="asChild"
45
+ :type="nativeType"
46
+ :disabled="disabled || undefined"
47
+ :aria-disabled="loading || disabled || undefined"
48
+ :aria-busy="loading || undefined"
49
+ :data-loading="loading || undefined"
50
+ :class="cn(buttonVariants({ variant, size, tone, fill }), props.class)"
51
+ >
52
+ <LoaderCircle v-if="loading" class="animate-spin" aria-hidden="true" />
53
+ <slot />
54
+ </Primitive>
55
+ </template>
@@ -0,0 +1,3 @@
1
+ export { buttonVariants, type ButtonVariants } from '../../variants/components/button'
2
+
3
+ export { default as Button } from './Button.vue'
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from 'reka-ui'
3
+ import type { ClassProps } from '../../lib/types'
4
+ import type { ButtonGroupVariants } from './index'
5
+ import { Primitive } from 'reka-ui'
6
+ import { cn } from '../../lib/utils'
7
+ import { buttonGroupVariants } from './index'
8
+
9
+ const props = withDefaults(
10
+ defineProps<PrimitiveProps & ClassProps & {
11
+ /** `horizontal` xếp ngang, `vertical` xếp dọc và gộp viền theo chiều dọc. */
12
+ orientation?: ButtonGroupVariants['orientation']
13
+ }>(),
14
+ { as: 'div', orientation: 'horizontal' },
15
+ )
16
+ </script>
17
+
18
+ <template>
19
+ <Primitive
20
+ :as="as"
21
+ :as-child="asChild"
22
+ role="group"
23
+ data-slot="button-group"
24
+ :data-orientation="props.orientation"
25
+ :class="cn(buttonGroupVariants({ orientation: props.orientation }), props.class)"
26
+ >
27
+ <slot />
28
+ </Primitive>
29
+ </template>
@@ -0,0 +1,30 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import { Separator } from 'reka-ui'
4
+ import { cn } from '../../lib/utils'
5
+
6
+ const props = withDefaults(
7
+ defineProps<ClassProps & {
8
+ /**
9
+ * Hướng của chính đường kẻ, không phải hướng của nhóm: nhóm nằm ngang thì
10
+ * cần đường kẻ **dọc** — nên mặc định là `vertical`.
11
+ */
12
+ orientation?: 'horizontal' | 'vertical'
13
+ }>(),
14
+ { orientation: 'vertical' },
15
+ )
16
+ </script>
17
+
18
+ <template>
19
+ <Separator
20
+ :orientation="props.orientation"
21
+ decorative
22
+ data-slot="button-group-separator"
23
+ :class="cn(
24
+ // `relative` để đường kẻ nằm trên viền của hai nút hai bên, không bị đè.
25
+ 'relative shrink-0 self-stretch bg-input',
26
+ props.orientation === 'vertical' ? 'my-px h-auto w-px' : 'mx-px h-px w-auto',
27
+ props.class,
28
+ )"
29
+ />
30
+ </template>
@@ -0,0 +1,29 @@
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
+ { as: 'div' },
10
+ )
11
+ </script>
12
+
13
+ <template>
14
+ <Primitive
15
+ :as="as"
16
+ :as-child="asChild"
17
+ data-slot="button-group-text"
18
+ :class="cn(
19
+ // Cùng chiều cao và bán kính với Button cỡ mặc định để ghép vào nhóm là
20
+ // vừa khít; không có hover vì đây là nhãn, không phải nút.
21
+ 'inline-flex h-8 items-center gap-1.5 rounded-lg border border-input bg-muted px-2.5',
22
+ 'text-sm font-medium text-muted-foreground',
23
+ '[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
24
+ props.class,
25
+ )"
26
+ >
27
+ <slot />
28
+ </Primitive>
29
+ </template>
@@ -0,0 +1,103 @@
1
+ <script setup lang="ts">
2
+ import type { ClassProps } from '../../lib/types'
3
+ import type { ButtonVariants } from '../button'
4
+ import type { SplitButtonItem } from './index'
5
+ import { computed, ref } from 'vue'
6
+ import { useI18n } from '../../composables/useI18n'
7
+ import { ChevronDown } from '../../lib/icons'
8
+ import { cn } from '../../lib/utils'
9
+ import { Button } from '../button'
10
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '../dropdown-menu'
11
+ import ButtonGroup from './ButtonGroup.vue'
12
+ import SplitButtonItems from './SplitButtonItems.vue'
13
+
14
+ const props = withDefaults(
15
+ defineProps<ClassProps & {
16
+ /** Nhãn của nút hành động chính. Slot mặc định ghi đè được. */
17
+ label?: string
18
+ /** Các mục trong menu xổ xuống. */
19
+ model?: SplitButtonItem[]
20
+ variant?: ButtonVariants['variant']
21
+ size?: Extract<ButtonVariants['size'], 'xs' | 'sm' | 'default' | 'lg'>
22
+ tone?: ButtonVariants['tone']
23
+ disabled?: boolean
24
+ /** Chỉ áp cho nút hành động chính; nút xổ menu vẫn bấm được. */
25
+ loading?: boolean
26
+ /** Tên cho nút xổ menu — nó chỉ có icon nên bắt buộc phải có. */
27
+ menuLabel?: string
28
+ }>(),
29
+ {
30
+ model: () => [],
31
+ size: 'default',
32
+ disabled: false,
33
+ loading: false,
34
+ },
35
+ )
36
+
37
+ const emit = defineEmits<{ click: [event: MouseEvent] }>()
38
+
39
+ const { t } = useI18n()
40
+
41
+ // Xem ghi chú ở SpeedDial về lý do không đặt trong `withDefaults`.
42
+ const menuLabel = computed(() => props.menuLabel ?? t('ui.splitButton.more'))
43
+
44
+ const open = ref(false)
45
+
46
+ /** Nút xổ menu là ô vuông cùng chiều cao với nút chính. */
47
+ const TRIGGER_SIZE = {
48
+ xs: 'icon-xs',
49
+ sm: 'icon-sm',
50
+ default: 'icon',
51
+ lg: 'icon-lg',
52
+ } as const
53
+
54
+ const triggerSize = computed(() => TRIGGER_SIZE[props.size])
55
+ </script>
56
+
57
+ <template>
58
+ <ButtonGroup
59
+ :class="cn(
60
+ // Trả lại viền trái cho nút xổ menu — ButtonGroup vốn bỏ nó đi để gộp
61
+ // viền chung. Màu lấy từ `currentColor` của chính nút nên tự hợp với mọi
62
+ // variant: nền đặc thì kẻ sáng, nền nhạt thì kẻ tối. `bg-input` của
63
+ // ButtonGroupSeparator không làm được vậy vì nó thừa kế màu chữ của NHÓM.
64
+ '[&>*:not(:first-child)]:border-l [&>*:not(:first-child)]:border-l-current/20',
65
+ props.class,
66
+ )"
67
+ >
68
+ <Button
69
+ :variant="variant"
70
+ :size="size"
71
+ :tone="tone"
72
+ :disabled="disabled"
73
+ :loading="loading"
74
+ @click="emit('click', $event)"
75
+ >
76
+ <slot name="icon" />
77
+ <slot>{{ label }}</slot>
78
+ </Button>
79
+
80
+ <DropdownMenu v-model:open="open">
81
+ <DropdownMenuTrigger as-child>
82
+ <Button
83
+ :variant="variant"
84
+ :size="triggerSize"
85
+ :tone="tone"
86
+ :disabled="disabled"
87
+ :aria-label="menuLabel"
88
+ >
89
+ <slot name="dropdownicon">
90
+ <ChevronDown
91
+ class="transition-transform duration-(--duration-base) motion-reduce:transition-none"
92
+ :class="open && '-rotate-180'"
93
+ />
94
+ </slot>
95
+ </Button>
96
+ </DropdownMenuTrigger>
97
+
98
+ <DropdownMenuContent align="end">
99
+ <SplitButtonItems :items="model" />
100
+ </DropdownMenuContent>
101
+ </DropdownMenu>
102
+ </ButtonGroup>
103
+ </template>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import type { SplitButtonItem } from './index'
3
+ import {
4
+ DropdownMenuItem,
5
+ DropdownMenuSeparator,
6
+ DropdownMenuShortcut,
7
+ DropdownMenuSub,
8
+ DropdownMenuSubContent,
9
+ DropdownMenuSubTrigger,
10
+ } from '../dropdown-menu'
11
+
12
+ defineProps<{ items: SplitButtonItem[] }>()
13
+
14
+ function run(item: SplitButtonItem): void {
15
+ item.command?.(item)
16
+ }
17
+ </script>
18
+
19
+ <template>
20
+ <!-- Component tự gọi chính nó để dựng submenu lồng nhau, không giới hạn cấp. -->
21
+ <template v-for="(item, index) in items" :key="index">
22
+ <DropdownMenuSeparator v-if="item.separator" />
23
+
24
+ <DropdownMenuSub v-else-if="item.items?.length">
25
+ <DropdownMenuSubTrigger :disabled="item.disabled">
26
+ <component :is="item.icon" v-if="item.icon" />
27
+ {{ item.label }}
28
+ </DropdownMenuSubTrigger>
29
+ <DropdownMenuSubContent>
30
+ <SplitButtonItems :items="item.items" />
31
+ </DropdownMenuSubContent>
32
+ </DropdownMenuSub>
33
+
34
+ <DropdownMenuItem
35
+ v-else
36
+ :as="item.url ? 'a' : undefined"
37
+ :href="item.url"
38
+ :target="item.target"
39
+ :disabled="item.disabled"
40
+ :variant="item.variant"
41
+ @select="run(item)"
42
+ >
43
+ <component :is="item.icon" v-if="item.icon" />
44
+ {{ item.label }}
45
+ <DropdownMenuShortcut v-if="item.shortcut">
46
+ {{ item.shortcut }}
47
+ </DropdownMenuShortcut>
48
+ </DropdownMenuItem>
49
+ </template>
50
+ </template>
@@ -0,0 +1,34 @@
1
+ import type { MenuActionItem } from '../../lib/menu'
2
+
3
+ export { buttonGroupVariants, type ButtonGroupVariants } from '../../variants/components/button-group'
4
+ export { default as ButtonGroup } from './ButtonGroup.vue'
5
+ export { default as ButtonGroupSeparator } from './ButtonGroupSeparator.vue'
6
+
7
+ export { default as ButtonGroupText } from './ButtonGroupText.vue'
8
+ // SplitButton KHÔNG phải một component riêng: nó chính là một ButtonGroup gồm
9
+ // hai nút — nút hành động và nút xổ menu — nên nằm cùng thư mục. Tách ra sẽ
10
+ // thành hai component nói cùng một chuyện. shadcn cũng không có SplitButton, ở
11
+ // đó nó chỉ là một ví dụ của ButtonGroup; PrimeVue phải làm component riêng vì
12
+ // không có ButtonGroup để dựng lên.
13
+ export { default as SplitButton } from './SplitButton.vue'
14
+
15
+ /**
16
+ * Một mục trong menu của `SplitButton`.
17
+ *
18
+ * Sáu trường chung (label, icon, command, url, target, disabled) nằm ở
19
+ * `MenuActionItem` — dùng chung với `SpeedDialItem` để hai component không trôi
20
+ * khỏi nhau. Phần thêm dưới đây là ba dạng loại trừ nhau, xét theo thứ tự:
21
+ * `separator` là đường kẻ, có `items` là submenu, còn lại là mục thường.
22
+ */
23
+ export interface SplitButtonItem extends MenuActionItem {
24
+ /** Đường kẻ ngăn nhóm; mọi trường khác bị bỏ qua. */
25
+ separator?: boolean
26
+ /** Có `items` thì mục thành submenu, `command` và `url` không còn tác dụng. */
27
+ items?: SplitButtonItem[]
28
+ /** Hành động nguy hiểm (xoá, thu hồi quyền) — hiện màu destructive. */
29
+ variant?: 'default' | 'destructive'
30
+ /** Phím tắt hiện mờ ở mép phải. */
31
+ shortcut?: string
32
+ }
33
+
34
+ export { default as SplitButtonItems } from './SplitButtonItems.vue'
@@ -0,0 +1,120 @@
1
+ <script setup lang="ts">
2
+ import type { DateValue } from '@internationalized/date'
3
+ import type { CalendarRootEmits, CalendarRootProps } from 'reka-ui'
4
+ import type { ClassProps } from '../../lib/types'
5
+ import { DateFormatter, getLocalTimeZone } from '@internationalized/date'
6
+ import {
7
+ CalendarCell,
8
+ CalendarCellTrigger,
9
+ CalendarGrid,
10
+ CalendarGridBody,
11
+ CalendarGridHead,
12
+ CalendarGridRow,
13
+ CalendarHeadCell,
14
+ CalendarHeader,
15
+ CalendarHeading,
16
+ CalendarNext,
17
+ CalendarPrev,
18
+ CalendarRoot,
19
+ useForwardPropsEmits,
20
+ } from 'reka-ui'
21
+ import { computed } from 'vue'
22
+ import { ChevronLeft, ChevronRight } from '../../lib/icons'
23
+ import { cn } from '../../lib/utils'
24
+
25
+ const props = withDefaults(
26
+ defineProps<CalendarRootProps & ClassProps>(),
27
+ { locale: 'vi-VN', weekStartsOn: 1, fixedWeeks: true },
28
+ )
29
+ const emits = defineEmits<CalendarRootEmits>()
30
+
31
+ const delegated = computed(() => {
32
+ const { class: _class, ...rest } = props
33
+ return rest
34
+ })
35
+
36
+ const forwarded = useForwardPropsEmits(delegated, emits)
37
+
38
+ /**
39
+ * Tên cho từng lưới tháng.
40
+ *
41
+ * reka render lưới là `<table role="application">`. Role đó **xoá sạch** ngữ
42
+ * nghĩa bảng và bắt trình đọc màn hình chuyển sang chế độ ứng dụng — nhờ vậy
43
+ * phím mũi tên đi thẳng vào lịch thay vì bị chế độ đọc nuốt mất. Cái giá: một
44
+ * vùng `application` không tên chỉ được đọc là "application". reka không tự
45
+ * đặt tên, nên phải tự khai `aria-label`.
46
+ */
47
+ function monthLabel(month: DateValue): string {
48
+ return new DateFormatter(props.locale, { month: 'long', year: 'numeric' })
49
+ .format(month.toDate(getLocalTimeZone()))
50
+ }
51
+
52
+ const navButton = cn(
53
+ 'inline-flex size-7 items-center justify-center rounded-md border border-input bg-background',
54
+ 'text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground',
55
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
56
+ 'disabled:pointer-events-none disabled:opacity-40',
57
+ )
58
+
59
+ const cellTrigger = cn(
60
+ 'relative inline-flex size-8 items-center justify-center rounded-md text-sm font-normal transition-colors',
61
+ 'hover:bg-accent hover:text-accent-foreground',
62
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
63
+ 'data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary',
64
+ 'data-[today]:font-semibold data-[today]:text-primary data-[selected]:data-[today]:text-primary-foreground',
65
+ 'data-[outside-view]:text-muted-foreground/50',
66
+ 'data-[unavailable]:text-muted-foreground/50 data-[unavailable]:line-through',
67
+ 'data-[disabled]:pointer-events-none data-[disabled]:opacity-40',
68
+ )
69
+ </script>
70
+
71
+ <template>
72
+ <CalendarRoot
73
+ v-slot="{ grid, weekDays }"
74
+ v-bind="forwarded"
75
+ :class="cn('rounded-md p-3', props.class)"
76
+ >
77
+ <CalendarHeader class="flex items-center justify-between pb-3">
78
+ <CalendarPrev :class="navButton">
79
+ <ChevronLeft class="size-4" />
80
+ </CalendarPrev>
81
+ <CalendarHeading class="text-sm font-medium capitalize" />
82
+ <CalendarNext :class="navButton">
83
+ <ChevronRight class="size-4" />
84
+ </CalendarNext>
85
+ </CalendarHeader>
86
+
87
+ <div class="flex flex-col gap-4 sm:flex-row">
88
+ <CalendarGrid
89
+ v-for="month in grid"
90
+ :key="month.value.toString()"
91
+ :aria-label="monthLabel(month.value)"
92
+ class="w-full border-collapse"
93
+ >
94
+ <CalendarGridHead>
95
+ <CalendarGridRow class="flex w-full justify-between">
96
+ <CalendarHeadCell
97
+ v-for="day in weekDays"
98
+ :key="day"
99
+ class="w-8 text-[0.7rem] font-normal capitalize text-muted-foreground"
100
+ >
101
+ {{ day }}
102
+ </CalendarHeadCell>
103
+ </CalendarGridRow>
104
+ </CalendarGridHead>
105
+
106
+ <CalendarGridBody class="grid">
107
+ <CalendarGridRow
108
+ v-for="(weekDates, index) in month.rows"
109
+ :key="`week-${index}`"
110
+ class="mt-1 flex w-full justify-between"
111
+ >
112
+ <CalendarCell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate" class="p-0">
113
+ <CalendarCellTrigger :day="weekDate" :month="month.value" :class="cellTrigger" />
114
+ </CalendarCell>
115
+ </CalendarGridRow>
116
+ </CalendarGridBody>
117
+ </CalendarGrid>
118
+ </div>
119
+ </CalendarRoot>
120
+ </template>
@@ -0,0 +1,127 @@
1
+ <script setup lang="ts">
2
+ import type { DateValue } from '@internationalized/date'
3
+ import type { RangeCalendarRootEmits, RangeCalendarRootProps } from 'reka-ui'
4
+ import type { ClassProps } from '../../lib/types'
5
+ import { DateFormatter, getLocalTimeZone } from '@internationalized/date'
6
+ import {
7
+ RangeCalendarCell,
8
+ RangeCalendarCellTrigger,
9
+ RangeCalendarGrid,
10
+ RangeCalendarGridBody,
11
+ RangeCalendarGridHead,
12
+ RangeCalendarGridRow,
13
+ RangeCalendarHeadCell,
14
+ RangeCalendarHeader,
15
+ RangeCalendarHeading,
16
+ RangeCalendarNext,
17
+ RangeCalendarPrev,
18
+ RangeCalendarRoot,
19
+ useForwardPropsEmits,
20
+ } from 'reka-ui'
21
+ import { computed } from 'vue'
22
+ import { ChevronLeft, ChevronRight } from '../../lib/icons'
23
+ import { cn } from '../../lib/utils'
24
+
25
+ const props = withDefaults(
26
+ defineProps<RangeCalendarRootProps & ClassProps>(),
27
+ { locale: 'vi-VN', weekStartsOn: 1, fixedWeeks: true, numberOfMonths: 2 },
28
+ )
29
+ const emits = defineEmits<RangeCalendarRootEmits>()
30
+
31
+ const delegated = computed(() => {
32
+ const { class: _class, ...rest } = props
33
+ return rest
34
+ })
35
+
36
+ const forwarded = useForwardPropsEmits(delegated, emits)
37
+
38
+ /**
39
+ * Tên cho từng lưới tháng. Xem chú thích cùng tên trong `Calendar.vue` —
40
+ * `role="application"` của reka không có tên, phải tự khai `aria-label`.
41
+ * Ở đây quan trọng hơn: lưới phạm vi mặc định hiện **hai** tháng, không có tên
42
+ * thì trình đọc màn hình gặp hai vùng giống hệt nhau.
43
+ */
44
+ function monthLabel(month: DateValue): string {
45
+ return new DateFormatter(props.locale, { month: 'long', year: 'numeric' })
46
+ .format(month.toDate(getLocalTimeZone()))
47
+ }
48
+
49
+ const navButton = cn(
50
+ 'inline-flex size-7 items-center justify-center rounded-md border border-input bg-background',
51
+ 'text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground',
52
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
53
+ 'disabled:pointer-events-none disabled:opacity-40',
54
+ )
55
+
56
+ /**
57
+ * Giống `Calendar` cộng ba trạng thái chỉ khoảng ngày mới có.
58
+ *
59
+ * Ô ở GIỮA khoảng bo vuông và tô nền nhạt, chỉ hai đầu mới bo tròn và tô đặc —
60
+ * nếu ô nào cũng bo tròn thì dải chọn đứt quãng, không đọc ra là một khoảng
61
+ * liền. `data-selection-start` / `data-selection-end` là của reka.
62
+ */
63
+ const cellTrigger = cn(
64
+ 'relative inline-flex size-8 items-center justify-center rounded-md text-sm font-normal transition-colors',
65
+ 'hover:bg-accent hover:text-accent-foreground',
66
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
67
+ 'data-[selected]:bg-accent data-[selected]:rounded-none',
68
+ 'data-[selection-start]:rounded-l-md data-[selection-start]:bg-primary data-[selection-start]:text-primary-foreground',
69
+ 'data-[selection-end]:rounded-r-md data-[selection-end]:bg-primary data-[selection-end]:text-primary-foreground',
70
+ 'data-[today]:font-semibold data-[today]:text-primary',
71
+ 'data-[selection-start]:data-[today]:text-primary-foreground data-[selection-end]:data-[today]:text-primary-foreground',
72
+ 'data-[outside-view]:text-muted-foreground/50',
73
+ 'data-[unavailable]:text-muted-foreground/50 data-[unavailable]:line-through',
74
+ 'data-[disabled]:pointer-events-none data-[disabled]:opacity-40',
75
+ )
76
+ </script>
77
+
78
+ <template>
79
+ <RangeCalendarRoot
80
+ v-slot="{ grid, weekDays }"
81
+ v-bind="forwarded"
82
+ :class="cn('rounded-md p-3', props.class)"
83
+ >
84
+ <RangeCalendarHeader class="flex items-center justify-between pb-3">
85
+ <RangeCalendarPrev :class="navButton">
86
+ <ChevronLeft class="size-4" />
87
+ </RangeCalendarPrev>
88
+ <RangeCalendarHeading class="text-sm font-medium capitalize" />
89
+ <RangeCalendarNext :class="navButton">
90
+ <ChevronRight class="size-4" />
91
+ </RangeCalendarNext>
92
+ </RangeCalendarHeader>
93
+
94
+ <div class="flex flex-col gap-4 sm:flex-row">
95
+ <RangeCalendarGrid
96
+ v-for="month in grid"
97
+ :key="month.value.toString()"
98
+ :aria-label="monthLabel(month.value)"
99
+ class="w-full border-collapse"
100
+ >
101
+ <RangeCalendarGridHead>
102
+ <RangeCalendarGridRow class="flex w-full justify-between">
103
+ <RangeCalendarHeadCell
104
+ v-for="day in weekDays"
105
+ :key="day"
106
+ class="w-8 text-[0.7rem] font-normal capitalize text-muted-foreground"
107
+ >
108
+ {{ day }}
109
+ </RangeCalendarHeadCell>
110
+ </RangeCalendarGridRow>
111
+ </RangeCalendarGridHead>
112
+
113
+ <RangeCalendarGridBody class="grid">
114
+ <RangeCalendarGridRow
115
+ v-for="(weekDates, index) in month.rows"
116
+ :key="`week-${index}`"
117
+ class="mt-1 flex w-full justify-between"
118
+ >
119
+ <RangeCalendarCell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate" class="p-0">
120
+ <RangeCalendarCellTrigger :day="weekDate" :month="month.value" :class="cellTrigger" />
121
+ </RangeCalendarCell>
122
+ </RangeCalendarGridRow>
123
+ </RangeCalendarGridBody>
124
+ </RangeCalendarGrid>
125
+ </div>
126
+ </RangeCalendarRoot>
127
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as Calendar } from './Calendar.vue'
2
+ export { default as RangeCalendar } from './RangeCalendar.vue'
@@ -0,0 +1,12 @@
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 :class="cn('surface rounded-lg border border-border bg-card text-card-foreground shadow-sm', props.class)">
10
+ <slot />
11
+ </div>
12
+ </template>