@nuxt/ui 3.0.0-alpha.8 → 3.0.0-beta.1

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 (310) hide show
  1. package/.nuxt/ui/accordion.ts +2 -2
  2. package/.nuxt/ui/alert.ts +122 -95
  3. package/.nuxt/ui/avatar-group.ts +14 -2
  4. package/.nuxt/ui/avatar.ts +16 -4
  5. package/.nuxt/ui/badge.ts +139 -93
  6. package/.nuxt/ui/breadcrumb.ts +5 -5
  7. package/.nuxt/ui/button-group.ts +13 -0
  8. package/.nuxt/ui/button.ts +167 -136
  9. package/.nuxt/ui/calendar.ts +103 -0
  10. package/.nuxt/ui/card.ts +27 -1
  11. package/.nuxt/ui/carousel.ts +9 -7
  12. package/.nuxt/ui/checkbox.ts +45 -27
  13. package/.nuxt/ui/chip.ts +44 -15
  14. package/.nuxt/ui/color-picker.ts +47 -0
  15. package/.nuxt/ui/command-palette.ts +28 -18
  16. package/.nuxt/ui/container.ts +1 -1
  17. package/.nuxt/ui/context-menu.ts +64 -46
  18. package/.nuxt/ui/drawer.ts +83 -15
  19. package/.nuxt/ui/dropdown-menu.ts +65 -47
  20. package/.nuxt/ui/form-field.ts +15 -7
  21. package/.nuxt/ui/index.ts +7 -1
  22. package/.nuxt/ui/input-menu.ts +150 -116
  23. package/.nuxt/ui/input-number.ts +235 -0
  24. package/.nuxt/ui/input.ts +111 -76
  25. package/.nuxt/ui/kbd.ts +18 -6
  26. package/.nuxt/ui/link.ts +3 -3
  27. package/.nuxt/ui/modal.ts +8 -7
  28. package/.nuxt/ui/navigation-menu.ts +244 -131
  29. package/.nuxt/ui/pin-input.ts +171 -0
  30. package/.nuxt/ui/popover.ts +2 -2
  31. package/.nuxt/ui/progress.ts +111 -72
  32. package/.nuxt/ui/radio-group.ts +45 -22
  33. package/.nuxt/ui/select-menu.ts +127 -96
  34. package/.nuxt/ui/select.ts +120 -84
  35. package/.nuxt/ui/separator.ts +60 -31
  36. package/.nuxt/ui/skeleton.ts +1 -1
  37. package/.nuxt/ui/slideover.ts +17 -9
  38. package/.nuxt/ui/slider.ts +61 -38
  39. package/.nuxt/ui/stepper.ts +202 -0
  40. package/.nuxt/ui/switch.ts +40 -22
  41. package/.nuxt/ui/table.ts +49 -31
  42. package/.nuxt/ui/tabs.ts +101 -73
  43. package/.nuxt/ui/textarea.ts +111 -76
  44. package/.nuxt/ui/toast.ts +53 -33
  45. package/.nuxt/ui/toaster.ts +31 -15
  46. package/.nuxt/ui/tooltip.ts +2 -2
  47. package/.nuxt/ui/tree.ts +154 -0
  48. package/.nuxt/ui.css +92 -0
  49. package/README.md +69 -18
  50. package/cli/commands/{init.mjs → make/component.mjs} +16 -4
  51. package/cli/commands/make/index.mjs +14 -0
  52. package/cli/commands/make/locale.mjs +64 -0
  53. package/cli/index.mjs +2 -2
  54. package/cli/package.json +2 -2
  55. package/cli/templates.mjs +62 -12
  56. package/cli/utils.mjs +14 -0
  57. package/dist/module.cjs +9 -170
  58. package/dist/module.d.cts +5 -15
  59. package/dist/module.d.mts +5 -15
  60. package/dist/module.d.ts +5 -15
  61. package/dist/module.json +2 -2
  62. package/dist/module.mjs +12 -167
  63. package/dist/runtime/components/Accordion.vue +8 -39
  64. package/dist/runtime/components/Alert.vue +25 -21
  65. package/dist/runtime/components/App.vue +15 -15
  66. package/dist/runtime/components/Avatar.vue +33 -21
  67. package/dist/runtime/components/AvatarGroup.vue +5 -7
  68. package/dist/runtime/components/Badge.vue +10 -8
  69. package/dist/runtime/components/Breadcrumb.vue +13 -34
  70. package/dist/runtime/components/Button.vue +5 -8
  71. package/dist/runtime/components/ButtonGroup.vue +5 -7
  72. package/dist/runtime/components/Calendar.vue +194 -0
  73. package/dist/runtime/components/Card.vue +10 -9
  74. package/dist/runtime/components/Carousel.vue +26 -17
  75. package/dist/runtime/components/Checkbox.vue +32 -38
  76. package/dist/runtime/components/Chip.vue +6 -8
  77. package/dist/runtime/components/Collapsible.vue +10 -11
  78. package/dist/runtime/components/ColorPicker.vue +297 -0
  79. package/dist/runtime/components/CommandPalette.vue +114 -98
  80. package/dist/runtime/components/Container.vue +4 -7
  81. package/dist/runtime/components/ContextMenu.vue +16 -69
  82. package/dist/runtime/components/ContextMenuContent.vue +14 -10
  83. package/dist/runtime/components/Drawer.vue +23 -12
  84. package/dist/runtime/components/DropdownMenu.vue +18 -59
  85. package/dist/runtime/components/DropdownMenuContent.vue +14 -10
  86. package/dist/runtime/components/Form.vue +78 -49
  87. package/dist/runtime/components/FormField.vue +28 -15
  88. package/dist/runtime/components/Icon.vue +1 -1
  89. package/dist/runtime/components/Input.vue +15 -7
  90. package/dist/runtime/components/InputMenu.vue +133 -66
  91. package/dist/runtime/components/InputNumber.vue +197 -0
  92. package/dist/runtime/components/Kbd.vue +5 -6
  93. package/dist/runtime/components/Link.vue +24 -13
  94. package/dist/runtime/components/LinkBase.vue +1 -1
  95. package/dist/runtime/components/Modal.vue +56 -34
  96. package/dist/runtime/components/NavigationMenu.vue +129 -112
  97. package/dist/runtime/components/OverlayProvider.vue +28 -0
  98. package/dist/runtime/components/Pagination.vue +18 -14
  99. package/dist/runtime/components/PinInput.vue +95 -0
  100. package/dist/runtime/components/Popover.vue +28 -14
  101. package/dist/runtime/components/Progress.vue +28 -12
  102. package/dist/runtime/components/RadioGroup.vue +9 -12
  103. package/dist/runtime/components/Select.vue +61 -35
  104. package/dist/runtime/components/SelectMenu.vue +201 -130
  105. package/dist/runtime/components/Separator.vue +6 -5
  106. package/dist/runtime/components/Skeleton.vue +4 -7
  107. package/dist/runtime/components/Slideover.vue +56 -33
  108. package/dist/runtime/components/Slider.vue +8 -7
  109. package/dist/runtime/components/Stepper.vue +170 -0
  110. package/dist/runtime/components/Switch.vue +19 -23
  111. package/dist/runtime/components/Table.vue +157 -32
  112. package/dist/runtime/components/Tabs.vue +12 -31
  113. package/dist/runtime/components/Textarea.vue +18 -9
  114. package/dist/runtime/components/Toast.vue +39 -25
  115. package/dist/runtime/components/Toaster.vue +31 -24
  116. package/dist/runtime/components/Tooltip.vue +9 -12
  117. package/dist/runtime/components/Tree.vue +196 -0
  118. package/dist/runtime/composables/defineLocale.d.ts +9 -0
  119. package/dist/runtime/composables/defineLocale.js +4 -0
  120. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  121. package/dist/runtime/composables/defineShortcuts.js +2 -2
  122. package/dist/runtime/composables/useFormField.d.ts +11 -4
  123. package/dist/runtime/composables/useFormField.js +19 -9
  124. package/dist/runtime/composables/useLocale.d.ts +4 -0
  125. package/dist/runtime/composables/useLocale.js +10 -0
  126. package/dist/runtime/composables/useOverlay.d.ts +30 -0
  127. package/dist/runtime/composables/useOverlay.js +70 -0
  128. package/dist/runtime/composables/useToast.d.ts +4 -3
  129. package/dist/runtime/composables/useToast.js +20 -6
  130. package/dist/runtime/index.css +1 -1
  131. package/dist/runtime/keyframes.css +1 -1
  132. package/dist/runtime/locale/ar.d.ts +2 -0
  133. package/dist/runtime/locale/ar.js +55 -0
  134. package/dist/runtime/locale/az.d.ts +2 -0
  135. package/dist/runtime/locale/az.js +54 -0
  136. package/dist/runtime/locale/bn.d.ts +2 -0
  137. package/dist/runtime/locale/bn.js +54 -0
  138. package/dist/runtime/locale/cs.d.ts +2 -0
  139. package/dist/runtime/locale/cs.js +54 -0
  140. package/dist/runtime/locale/da.d.ts +2 -0
  141. package/dist/runtime/locale/da.js +54 -0
  142. package/dist/runtime/locale/de.d.ts +2 -0
  143. package/dist/runtime/locale/de.js +54 -0
  144. package/dist/runtime/locale/el.d.ts +2 -0
  145. package/dist/runtime/locale/el.js +54 -0
  146. package/dist/runtime/locale/en.d.ts +2 -0
  147. package/dist/runtime/locale/en.js +54 -0
  148. package/dist/runtime/locale/es.d.ts +2 -0
  149. package/dist/runtime/locale/es.js +54 -0
  150. package/dist/runtime/locale/et.d.ts +2 -0
  151. package/dist/runtime/locale/et.js +54 -0
  152. package/dist/runtime/locale/fa_ir.d.ts +2 -0
  153. package/dist/runtime/locale/fa_ir.js +55 -0
  154. package/dist/runtime/locale/fi.d.ts +2 -0
  155. package/dist/runtime/locale/fi.js +54 -0
  156. package/dist/runtime/locale/fr.d.ts +2 -0
  157. package/dist/runtime/locale/fr.js +54 -0
  158. package/dist/runtime/locale/he.d.ts +2 -0
  159. package/dist/runtime/locale/he.js +53 -0
  160. package/dist/runtime/locale/hi.d.ts +2 -0
  161. package/dist/runtime/locale/hi.js +54 -0
  162. package/dist/runtime/locale/hu.d.ts +2 -0
  163. package/dist/runtime/locale/hu.js +54 -0
  164. package/dist/runtime/locale/id.d.ts +2 -0
  165. package/dist/runtime/locale/id.js +54 -0
  166. package/dist/runtime/locale/index.d.ts +34 -0
  167. package/dist/runtime/locale/index.js +34 -0
  168. package/dist/runtime/locale/it.d.ts +2 -0
  169. package/dist/runtime/locale/it.js +54 -0
  170. package/dist/runtime/locale/ja.d.ts +2 -0
  171. package/dist/runtime/locale/ja.js +54 -0
  172. package/dist/runtime/locale/km.d.ts +2 -0
  173. package/dist/runtime/locale/km.js +54 -0
  174. package/dist/runtime/locale/ko.d.ts +2 -0
  175. package/dist/runtime/locale/ko.js +54 -0
  176. package/dist/runtime/locale/nb_no.d.ts +2 -0
  177. package/dist/runtime/locale/nb_no.js +54 -0
  178. package/dist/runtime/locale/nl.d.ts +2 -0
  179. package/dist/runtime/locale/nl.js +54 -0
  180. package/dist/runtime/locale/pl.d.ts +2 -0
  181. package/dist/runtime/locale/pl.js +54 -0
  182. package/dist/runtime/locale/pt.d.ts +2 -0
  183. package/dist/runtime/locale/pt.js +54 -0
  184. package/dist/runtime/locale/pt_br.d.ts +2 -0
  185. package/dist/runtime/locale/pt_br.js +54 -0
  186. package/dist/runtime/locale/ru.d.ts +2 -0
  187. package/dist/runtime/locale/ru.js +54 -0
  188. package/dist/runtime/locale/sk.d.ts +2 -0
  189. package/dist/runtime/locale/sk.js +54 -0
  190. package/dist/runtime/locale/sv.d.ts +2 -0
  191. package/dist/runtime/locale/sv.js +54 -0
  192. package/dist/runtime/locale/th.d.ts +2 -0
  193. package/dist/runtime/locale/th.js +54 -0
  194. package/dist/runtime/locale/tr.d.ts +2 -0
  195. package/dist/runtime/locale/tr.js +54 -0
  196. package/dist/runtime/locale/uk.d.ts +2 -0
  197. package/dist/runtime/locale/uk.js +54 -0
  198. package/dist/runtime/locale/vi.d.ts +2 -0
  199. package/dist/runtime/locale/vi.js +54 -0
  200. package/dist/runtime/locale/zh_cn.d.ts +2 -0
  201. package/dist/runtime/locale/zh_cn.js +54 -0
  202. package/dist/runtime/locale/zh_tw.d.ts +2 -0
  203. package/dist/runtime/locale/zh_tw.js +54 -0
  204. package/dist/runtime/plugins/colors.js +8 -5
  205. package/dist/runtime/types/form.d.ts +29 -15
  206. package/dist/runtime/types/form.js +2 -2
  207. package/dist/runtime/types/index.d.ts +8 -0
  208. package/dist/runtime/types/index.js +8 -0
  209. package/dist/runtime/types/locale.d.ts +56 -0
  210. package/dist/runtime/types/locale.js +0 -0
  211. package/dist/runtime/types/utils.d.ts +7 -3
  212. package/dist/runtime/utils/form.d.ts +5 -9
  213. package/dist/runtime/utils/form.js +113 -50
  214. package/dist/runtime/utils/index.d.ts +1 -1
  215. package/dist/runtime/utils/index.js +15 -2
  216. package/dist/runtime/utils/link.d.ts +1 -1
  217. package/dist/runtime/utils/locale.d.ts +15 -0
  218. package/dist/runtime/utils/locale.js +25 -0
  219. package/dist/runtime/utils/tv.d.ts +1 -0
  220. package/dist/runtime/utils/tv.js +4 -0
  221. package/dist/runtime/vue/components/Icon.vue +2 -2
  222. package/dist/runtime/vue/components/Link.vue +87 -23
  223. package/dist/runtime/vue/composables/useAppConfig.d.ts +1 -0
  224. package/dist/runtime/vue/composables/useAppConfig.js +2 -0
  225. package/dist/runtime/vue/plugins/head.d.ts +1 -1
  226. package/dist/runtime/vue/plugins/head.js +3 -3
  227. package/dist/runtime/vue/stubs.d.ts +19 -0
  228. package/dist/runtime/vue/stubs.js +37 -0
  229. package/dist/shared/{ui.BufKhDiD.mjs → ui.DSPu6Y8j.mjs} +1071 -409
  230. package/dist/shared/{ui.BU7wzH0D.cjs → ui.DfK2RX6G.cjs} +1074 -409
  231. package/dist/unplugin.cjs +62 -26
  232. package/dist/unplugin.d.cts +17 -3
  233. package/dist/unplugin.d.mts +17 -3
  234. package/dist/unplugin.d.ts +17 -3
  235. package/dist/unplugin.mjs +61 -25
  236. package/dist/vite.cjs +3 -2
  237. package/dist/vite.d.cts +2 -0
  238. package/dist/vite.d.mts +2 -0
  239. package/dist/vite.d.ts +2 -0
  240. package/dist/vite.mjs +3 -2
  241. package/package.json +110 -67
  242. package/dist/chunks/component-meta.cjs +0 -73264
  243. package/dist/chunks/component-meta.mjs +0 -73262
  244. package/dist/client/devtools/200.html +0 -1
  245. package/dist/client/devtools/404.html +0 -1
  246. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKK58UfivUw4aw-SK92LTmKP0.woff2 +0 -0
  247. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKy58UfivUw-9uYm8d48E4.woff2 +0 -0
  248. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2 +0 -0
  249. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu6-K6z9mXgjU0-EkYdMs3MAX.woff2 +0 -0
  250. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-7DW3w-R7n06NbhGy.woff +0 -0
  251. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDG3w-leGNfkTmsj.woff +0 -0
  252. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDW3w-ciElMF03ku.woff +0 -0
  253. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JCm3w-sB722Uoa0f.woff +0 -0
  254. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JDW3w-PBDI1JDjwV.woff +0 -0
  255. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8gCm3w-0q1hqVn09O.woff +0 -0
  256. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff +0 -0
  257. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9uCm3w-5TKCIs6EEw.woff +0 -0
  258. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat_XDW3w-r2swRDGfn2.woff +0 -0
  259. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAC5thTQ-ldB60l5U8r.woff +0 -0
  260. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpthTQ-wbFKGFDrgo.woff +0 -0
  261. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpxhTQ-LLUBv5jskj.woff +0 -0
  262. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTQ-F71RdTRbNg.woff +0 -0
  263. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwA_JxhTQ-6nh65gZkc0.woff +0 -0
  264. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTQ-aMoWEJLmTt.woff +0 -0
  265. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTQ-WMBvmLOgKm.woff +0 -0
  266. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAop1hTQ-utGC2hnWq2.woff +0 -0
  267. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTQ-YpyTieVa5B.woff +0 -0
  268. package/dist/client/devtools/_nuxt/Bj9hdafK.js +0 -1
  269. package/dist/client/devtools/_nuxt/DM3_wAgz.js +0 -62
  270. package/dist/client/devtools/_nuxt/builds/latest.json +0 -1
  271. package/dist/client/devtools/_nuxt/builds/meta/e6b425f7-b919-4014-915b-0ea07c316790.json +0 -1
  272. package/dist/client/devtools/_nuxt/entry.DaJP-ZMB.css +0 -24
  273. package/dist/client/devtools/_nuxt/error-404.B0Nmv3fV.css +0 -1
  274. package/dist/client/devtools/_nuxt/error-500.C8fgTxVz.css +0 -1
  275. package/dist/client/devtools/_nuxt/hKiujHsR.js +0 -1
  276. package/dist/client/devtools/favicon.svg +0 -1
  277. package/dist/client/devtools/index.html +0 -1
  278. package/dist/devtools/runtime/DevtoolsRenderer.vue +0 -53
  279. package/dist/devtools/runtime/examples/AvatarGroupExample.vue +0 -7
  280. package/dist/devtools/runtime/examples/ButtonGroupExample.vue +0 -8
  281. package/dist/devtools/runtime/examples/CardExample.vue +0 -13
  282. package/dist/devtools/runtime/examples/CarouselExample.vue +0 -13
  283. package/dist/devtools/runtime/examples/ChipExample.vue +0 -5
  284. package/dist/devtools/runtime/examples/CollapsibleExample.vue +0 -8
  285. package/dist/devtools/runtime/examples/CommandPaletteExample.vue +0 -29
  286. package/dist/devtools/runtime/examples/ContainerExample.vue +0 -5
  287. package/dist/devtools/runtime/examples/ContextMenuExample.vue +0 -5
  288. package/dist/devtools/runtime/examples/DrawerExample.vue +0 -8
  289. package/dist/devtools/runtime/examples/DropdownMenuExample.vue +0 -5
  290. package/dist/devtools/runtime/examples/FormExample.vue +0 -30
  291. package/dist/devtools/runtime/examples/FormFieldExample.vue +0 -5
  292. package/dist/devtools/runtime/examples/LinkExample.vue +0 -5
  293. package/dist/devtools/runtime/examples/ModalExample.vue +0 -8
  294. package/dist/devtools/runtime/examples/PopoverExample.vue +0 -8
  295. package/dist/devtools/runtime/examples/SkeletonExample.vue +0 -3
  296. package/dist/devtools/runtime/examples/SlideoverExample.vue +0 -8
  297. package/dist/devtools/runtime/examples/ToasterExample.vue +0 -11
  298. package/dist/devtools/runtime/examples/TooltipExample.vue +0 -5
  299. package/dist/runtime/components/ModalProvider.vue +0 -12
  300. package/dist/runtime/components/SlideoverProvider.vue +0 -12
  301. package/dist/runtime/composables/extendDevtoolsMeta.d.ts +0 -7
  302. package/dist/runtime/composables/extendDevtoolsMeta.js +0 -2
  303. package/dist/runtime/composables/useModal.d.ts +0 -17
  304. package/dist/runtime/composables/useModal.js +0 -46
  305. package/dist/runtime/composables/useSlideover.d.ts +0 -17
  306. package/dist/runtime/composables/useSlideover.js +0 -46
  307. package/dist/runtime/plugins/modal.d.ts +0 -2
  308. package/dist/runtime/plugins/modal.js +0 -10
  309. package/dist/runtime/plugins/slideover.d.ts +0 -2
  310. package/dist/runtime/plugins/slideover.js +0 -10
@@ -1,28 +1,38 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
3
- import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps } from 'radix-vue'
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, CollapsibleRootProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/navigation-menu'
7
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
8
8
  import type { AvatarProps, BadgeProps, LinkProps } from '../types'
9
9
  import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString } from '../types/utils'
10
10
 
11
- const appConfig = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
11
+ const appConfigNavigationMenu = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
12
12
 
13
- const navigationMenu = tv({ extend: tv(theme), ...(appConfig.ui?.navigationMenu || {}) })
13
+ const navigationMenu = tv({ extend: tv(theme), ...(appConfigNavigationMenu.ui?.navigationMenu || {}) })
14
14
 
15
- export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'children'> {
15
+ export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'children' | 'type'> {
16
16
  /** Description is only used when `orientation` is `horizontal`. */
17
17
  description?: string
18
18
  }
19
19
 
20
- export interface NavigationMenuItem extends Omit<LinkProps, 'raw' | 'custom'> {
20
+ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'>, Pick<CollapsibleRootProps, 'defaultOpen' | 'open'> {
21
21
  label?: string
22
22
  icon?: string
23
23
  avatar?: AvatarProps
24
+ /**
25
+ * Display a badge on the item.
26
+ * `{ size: 'sm', color: 'neutral', variant: 'outline' }`{lang="ts-type"}
27
+ */
24
28
  badge?: string | number | BadgeProps
25
29
  trailingIcon?: string
30
+ /**
31
+ * The type of the item.
32
+ * The `label` type only works on `vertical` orientation.
33
+ * @defaultValue 'link'
34
+ */
35
+ type?: 'label' | 'link'
26
36
  slot?: string
27
37
  value?: string
28
38
  children?: NavigationMenuChildItem[]
@@ -31,7 +41,7 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'raw' | 'custom'> {
31
41
 
32
42
  type NavigationMenuVariants = VariantProps<typeof navigationMenu>
33
43
 
34
- export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'modelValue' | 'skipDelayDuration'> {
44
+ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'modelValue' | 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'> {
35
45
  /**
36
46
  * The element or component this component should render as.
37
47
  * @defaultValue 'div'
@@ -42,6 +52,12 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'd
42
52
  * @defaultValue appConfig.ui.icons.chevronDown
43
53
  */
44
54
  trailingIcon?: string
55
+ /**
56
+ * The icon displayed when the item is an external link.
57
+ * Set to `false` to hide the external icon.
58
+ * @defaultValue appConfig.ui.icons.external
59
+ */
60
+ externalIcon?: boolean | string
45
61
  items?: T
46
62
  color?: NavigationMenuVariants['color']
47
63
  variant?: NavigationMenuVariants['variant']
@@ -50,11 +66,23 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'd
50
66
  * @defaultValue 'horizontal'
51
67
  */
52
68
  orientation?: NavigationMenuRootProps['orientation']
69
+ /**
70
+ * Collapse the navigation menu to only show icons.
71
+ * Only works when `orientation` is `vertical`.
72
+ * @defaultValue false
73
+ */
74
+ collapsed?: boolean
53
75
  /** Display a line next to the active item. */
54
76
  highlight?: boolean
55
77
  highlightColor?: NavigationMenuVariants['highlightColor']
56
78
  /** The content of the menu. */
57
79
  content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'>
80
+ /**
81
+ * The orientation of the content.
82
+ * Only works when `orientation` is `horizontal`.
83
+ * @defaultValue 'horizontal'
84
+ */
85
+ contentOrientation?: NavigationMenuVariants['contentOrientation']
58
86
  /**
59
87
  * Display an arrow alongside the menu.
60
88
  * @defaultValue false
@@ -80,51 +108,13 @@ export type NavigationMenuSlots<T extends { slot?: string }> = {
80
108
  'item-trailing': SlotProps<T>
81
109
  'item-content': SlotProps<T>
82
110
  } & DynamicSlots<T, SlotProps<T>>
83
-
84
- extendDevtoolsMeta({
85
- ignoreProps: ['items'],
86
- defaultProps: {
87
- items: [
88
- [{
89
- label: 'Documentation',
90
- icon: 'i-lucide-book-open',
91
- badge: 10,
92
- children: [{
93
- label: 'Introduction',
94
- description: 'Fully styled and customizable components for Nuxt.',
95
- icon: 'i-lucide-house'
96
- }, {
97
- label: 'Installation',
98
- description: 'Learn how to install and configure Nuxt UI in your application.',
99
- icon: 'i-lucide-cloud-download'
100
- }, {
101
- label: 'Theming',
102
- description: 'Learn how to customize the look and feel of the components.',
103
- icon: 'i-lucide-swatch-book'
104
- }, {
105
- label: 'Shortcuts',
106
- description: 'Learn how to display and define keyboard shortcuts in your app.',
107
- icon: 'i-lucide-monitor'
108
- }]
109
- }, {
110
- label: 'GitHub',
111
- icon: 'i-simple-icons-github',
112
- to: 'https://github.com/nuxt/ui',
113
- target: '_blank'
114
- }, {
115
- label: 'Help',
116
- icon: 'i-lucide-circle-help',
117
- disabled: true
118
- }]
119
- ]
120
- }
121
- })
122
111
  </script>
123
112
 
124
113
  <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<NavigationMenuItem>">
125
- import { computed, reactive, toRef } from 'vue'
126
- import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, useForwardPropsEmits } from 'radix-vue'
114
+ import { computed, toRef } from 'vue'
115
+ import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, useForwardPropsEmits } from 'reka-ui'
127
116
  import { createReusableTemplate } from '@vueuse/core'
117
+ import { useAppConfig } from '#imports'
128
118
  import { get } from '../utils'
129
119
  import { pickLinkProps } from '../utils/link'
130
120
  import ULinkBase from './LinkBase.vue'
@@ -136,27 +126,44 @@ import UCollapsible from './Collapsible.vue'
136
126
 
137
127
  const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
138
128
  orientation: 'horizontal',
129
+ contentOrientation: 'horizontal',
130
+ externalIcon: true,
139
131
  delayDuration: 0,
132
+ unmountOnHide: true,
140
133
  labelKey: 'label'
141
134
  })
142
135
  const emits = defineEmits<NavigationMenuEmits>()
143
136
  const slots = defineSlots<NavigationMenuSlots<T>>()
144
137
 
145
- const rootProps = useForwardPropsEmits(reactive({
138
+ const rootProps = useForwardPropsEmits(computed(() => ({
146
139
  as: props.as,
147
140
  modelValue: props.modelValue,
148
141
  defaultValue: props.defaultValue,
149
142
  delayDuration: props.delayDuration,
150
143
  skipDelayDuration: props.skipDelayDuration,
151
- orientation: props.orientation
152
- }), emits)
144
+ orientation: props.orientation,
145
+ disableClickTrigger: props.disableClickTrigger,
146
+ disableHoverTrigger: props.disableHoverTrigger,
147
+ disablePointerLeaveClose: props.disablePointerLeaveClose,
148
+ unmountOnHide: props.unmountOnHide
149
+ })), emits)
153
150
 
154
151
  const contentProps = toRef(() => props.content)
155
152
 
156
- const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, active?: boolean, index: number }>()
153
+ const appConfig = useAppConfig()
154
+ const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, active?: boolean }>()
155
+ const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, level?: number }>({
156
+ props: {
157
+ item: Object,
158
+ index: Number,
159
+ level: Number
160
+ }
161
+ })
157
162
 
158
163
  const ui = computed(() => navigationMenu({
159
164
  orientation: props.orientation,
165
+ contentOrientation: props.contentOrientation,
166
+ collapsed: props.collapsed,
160
167
  color: props.color,
161
168
  variant: props.variant,
162
169
  highlight: props.highlight,
@@ -167,22 +174,25 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
167
174
  </script>
168
175
 
169
176
  <template>
170
- <DefineItemTemplate v-slot="{ item, active, index }">
177
+ <DefineLinkTemplate v-slot="{ item, active, index }">
171
178
  <slot :name="item.slot || 'item'" :item="(item as T)" :index="index">
172
179
  <slot :name="item.slot ? `${item.slot}-leading` : 'item-leading'" :item="(item as T)" :active="active" :index="index">
173
180
  <UAvatar v-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active, disabled: !!item.disabled })" />
174
181
  <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active, disabled: !!item.disabled })" />
175
182
  </slot>
176
183
 
177
- <span v-if="get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : 'item-label']" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
184
+ <span
185
+ v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : 'item-label'])"
186
+ :class="ui.linkLabel({ class: props.ui?.linkLabel })"
187
+ >
178
188
  <slot :name="item.slot ? `${item.slot}-label` : 'item-label'" :item="(item as T)" :active="active" :index="index">
179
189
  {{ get(item, props.labelKey as string) }}
180
190
  </slot>
181
191
 
182
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
192
+ <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
183
193
  </span>
184
194
 
185
- <span v-if="item.badge || item.children?.length || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing']" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
195
+ <span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing'])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
186
196
  <slot :name="item.slot ? `${item.slot}-trailing` : 'item-trailing'" :item="(item as T)" :active="active" :index="index">
187
197
  <UBadge
188
198
  v-if="item.badge"
@@ -194,77 +204,84 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
194
204
  />
195
205
 
196
206
  <UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
207
+ <UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
197
208
  </slot>
198
209
  </span>
199
210
  </slot>
200
- </DefineItemTemplate>
211
+ </DefineLinkTemplate>
201
212
 
202
- <NavigationMenuRoot v-bind="rootProps" :data-orientation="orientation" :class="ui.root({ class: [props.class, props.ui?.root] })">
203
- <template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
204
- <NavigationMenuList :class="ui.list({ class: props.ui?.list })">
213
+ <DefineItemTemplate v-slot="{ item, index, level = 0 }">
214
+ <component
215
+ :is="(orientation === 'vertical' && item.children?.length && !collapsed) ? UCollapsible : NavigationMenuItem"
216
+ as="li"
217
+ :value="item.value || String(index)"
218
+ :default-open="item.defaultOpen"
219
+ :unmount-on-hide="(orientation === 'vertical' && item.children?.length && !collapsed) ? unmountOnHide : undefined"
220
+ :open="item.open"
221
+ >
222
+ <div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
223
+ <ReuseLinkTemplate :item="(item as T)" :index="index" />
224
+ </div>
225
+ <ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && !collapsed) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
205
226
  <component
206
- :is="(item.children?.length && orientation === 'vertical') ? UCollapsible : NavigationMenuItem"
207
- v-for="(item, index) in list"
208
- :key="`list-${listIndex}-${index}`"
209
- as="li"
210
- :value="item.value || String(index)"
211
- :class="ui.item({ class: props.ui?.item })"
227
+ :is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
228
+ as-child
229
+ :active="active || item.active"
230
+ :disabled="item.disabled"
231
+ @select="item.onSelect"
212
232
  >
213
- <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
214
- <component
215
- :is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
216
- as-child
217
- :active="active"
218
- :disabled="item.disabled"
219
- @select="item.onSelect"
220
- >
221
- <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active, disabled: !!item.disabled })">
222
- <ReuseItemTemplate :item="(item as T)" :active="active" :index="index" />
223
- </ULinkBase>
224
- </component>
225
-
226
- <NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
227
- <slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="(item as T)" :active="active" :index="index">
228
- <ul :class="ui.childList({ class: props.ui?.childList })">
229
- <li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
230
- <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
231
- <NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
232
- <ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
233
- <UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />
234
-
235
- <div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
236
- <p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
237
- {{ get(childItem, props.labelKey as string) }}
238
-
239
- <UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
240
- </p>
241
- <p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
242
- {{ childItem.description }}
243
- </p>
244
- </div>
245
- </ULinkBase>
246
- </NavigationMenuLink>
247
- </ULink>
248
- </li>
249
- </ul>
250
- </slot>
251
- </NavigationMenuContent>
252
- </ULink>
233
+ <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
234
+ <ReuseLinkTemplate :item="(item as T)" :active="active || item.active" :index="index" />
235
+ </ULinkBase>
236
+ </component>
253
237
 
254
- <template v-if="orientation === 'vertical' && item.children?.length" #content>
238
+ <NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
239
+ <slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="(item as T)" :active="active" :index="index">
255
240
  <ul :class="ui.childList({ class: props.ui?.childList })">
256
241
  <li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
257
242
  <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
258
243
  <NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
259
- <ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled })">
260
- <ReuseItemTemplate :item="(childItem as T)" :active="childActive" :index="childIndex" />
244
+ <ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
245
+ <UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />
246
+
247
+ <div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
248
+ <p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
249
+ {{ get(childItem, props.labelKey as string) }}
250
+
251
+ <UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
252
+ </p>
253
+ <p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
254
+ {{ childItem.description }}
255
+ </p>
256
+ </div>
261
257
  </ULinkBase>
262
258
  </NavigationMenuLink>
263
259
  </ULink>
264
260
  </li>
265
261
  </ul>
266
- </template>
267
- </component>
262
+ </slot>
263
+ </NavigationMenuContent>
264
+ </ULink>
265
+
266
+ <template v-if="orientation === 'vertical' && item.children?.length && !collapsed" #content>
267
+ <ul :class="ui.childList({ class: props.ui?.childList })">
268
+ <ReuseItemTemplate
269
+ v-for="(childItem, childIndex) in item.children"
270
+ :key="childIndex"
271
+ :item="childItem"
272
+ :index="childIndex"
273
+ :level="level + 1"
274
+ :class="ui.childItem({ class: props.ui?.childItem })"
275
+ />
276
+ </ul>
277
+ </template>
278
+ </component>
279
+ </DefineItemTemplate>
280
+
281
+ <NavigationMenuRoot v-bind="rootProps" :data-collapsed="collapsed" :class="ui.root({ class: [props.class, props.ui?.root] })">
282
+ <template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
283
+ <NavigationMenuList :class="ui.list({ class: props.ui?.list })">
284
+ <ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="ui.item({ class: props.ui?.item })" />
268
285
  </NavigationMenuList>
269
286
 
270
287
  <div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" />
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import { useOverlay, type Overlay } from '../composables/useOverlay'
3
+
4
+ const { overlays, unMount, close } = useOverlay()
5
+
6
+ const mountedOverlays = computed(() => overlays.filter((overlay: Overlay) => overlay.isMounted))
7
+
8
+ const onAfterLeave = (id: symbol) => {
9
+ close(id)
10
+ unMount(id)
11
+ }
12
+
13
+ const onClose = (id: symbol, value: any) => {
14
+ close(id, value)
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <component
20
+ :is="overlay.component"
21
+ v-for="overlay in mountedOverlays"
22
+ :key="overlay.id"
23
+ v-bind="overlay.props"
24
+ v-model:open="overlay.modelValue"
25
+ @close="(value:any) => onClose(overlay.id, value)"
26
+ @after:leave="onAfterLeave(overlay.id)"
27
+ />
28
+ </template>
@@ -1,18 +1,17 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
- import type { PaginationRootProps, PaginationRootEmits } from 'radix-vue'
2
+ import type { PaginationRootProps, PaginationRootEmits } from 'reka-ui'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import type { RouteLocationRaw } from '#vue-router'
6
5
  import _appConfig from '#build/app.config'
7
6
  import theme from '#build/ui/pagination'
8
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
9
8
  import type { ButtonProps } from '../types'
10
9
 
11
- const appConfig = _appConfig as AppConfig & { ui: { pagination: Partial<typeof theme> } }
10
+ const appConfigPagination = _appConfig as AppConfig & { ui: { pagination: Partial<typeof theme> } }
12
11
 
13
- const pagination = tv({ extend: tv(theme), ...(appConfig.ui?.pagination || {}) })
12
+ const pagination = tv({ extend: tv(theme), ...(appConfigPagination.ui?.pagination || {}) })
14
13
 
15
- export interface PaginationProps extends Pick<PaginationRootProps, 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'> {
14
+ export interface PaginationProps extends Partial<Pick<PaginationRootProps, 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'>> {
16
15
  /**
17
16
  * The element or component this component should render as.
18
17
  * @defaultValue 'div'
@@ -98,14 +97,14 @@ export interface PaginationSlots {
98
97
  index: number
99
98
  }): any
100
99
  }
101
-
102
- extendDevtoolsMeta({ defaultProps: { total: 50 } })
103
100
  </script>
104
101
 
105
102
  <script setup lang="ts">
106
- import { PaginationRoot, PaginationList, PaginationListItem, PaginationFirst, PaginationPrev, PaginationEllipsis, PaginationNext, PaginationLast, useForwardPropsEmits } from 'radix-vue'
103
+ import { computed } from 'vue'
104
+ import { PaginationRoot, PaginationList, PaginationListItem, PaginationFirst, PaginationPrev, PaginationEllipsis, PaginationNext, PaginationLast, useForwardPropsEmits } from 'reka-ui'
107
105
  import { reactivePick } from '@vueuse/core'
108
106
  import { useAppConfig } from '#imports'
107
+ import { useLocale } from '../composables/useLocale'
109
108
  import UButton from './Button.vue'
110
109
 
111
110
  const props = withDefaults(defineProps<PaginationProps>(), {
@@ -124,9 +123,14 @@ const emits = defineEmits<PaginationEmits>()
124
123
  const slots = defineSlots<PaginationSlots>()
125
124
 
126
125
  const appConfig = useAppConfig()
127
-
126
+ const { dir } = useLocale()
128
127
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultPage', 'disabled', 'itemsPerPage', 'page', 'showEdges', 'siblingCount', 'total'), emits)
129
128
 
129
+ const firstIcon = computed(() => props.firstIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleRight : appConfig.ui.icons.chevronDoubleLeft))
130
+ const prevIcon = computed(() => props.prevIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronRight : appConfig.ui.icons.chevronLeft))
131
+ const nextIcon = computed(() => props.nextIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronLeft : appConfig.ui.icons.chevronRight))
132
+ const lastIcon = computed(() => props.lastIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleLeft : appConfig.ui.icons.chevronDoubleRight))
133
+
130
134
  // eslint-disable-next-line vue/no-dupe-keys
131
135
  const ui = pagination()
132
136
  </script>
@@ -136,12 +140,12 @@ const ui = pagination()
136
140
  <PaginationList v-slot="{ items }" :class="ui.list({ class: props.ui?.list })">
137
141
  <PaginationFirst v-if="showControls || !!slots.first" as-child>
138
142
  <slot name="first">
139
- <UButton :color="color" :variant="variant" :size="size" :icon="firstIcon || appConfig.ui.icons.chevronDoubleLeft" :to="to?.(1)" />
143
+ <UButton :color="color" :variant="variant" :size="size" :icon="firstIcon" :to="to?.(1)" />
140
144
  </slot>
141
145
  </PaginationFirst>
142
146
  <PaginationPrev v-if="showControls || !!slots.prev" as-child>
143
147
  <slot name="prev">
144
- <UButton :color="color" :variant="variant" :size="size" :icon="prevIcon || appConfig.ui.icons.chevronLeft" :to="page > 1 ? to?.(page - 1) : undefined" />
148
+ <UButton :color="color" :variant="variant" :size="size" :icon="prevIcon" :to="page > 1 ? to?.(page - 1) : undefined" />
145
149
  </slot>
146
150
  </PaginationPrev>
147
151
 
@@ -169,12 +173,12 @@ const ui = pagination()
169
173
 
170
174
  <PaginationNext v-if="showControls || !!slots.next" as-child>
171
175
  <slot name="next">
172
- <UButton :color="color" :variant="variant" :size="size" :icon="nextIcon || appConfig.ui.icons.chevronRight" :to="page < pageCount ? to?.(pageCount) : undefined" />
176
+ <UButton :color="color" :variant="variant" :size="size" :icon="nextIcon" :to="page < pageCount ? to?.(pageCount) : undefined" />
173
177
  </slot>
174
178
  </PaginationNext>
175
179
  <PaginationLast v-if="showControls || !!slots.last" as-child>
176
180
  <slot name="last">
177
- <UButton :color="color" :variant="variant" :size="size" :icon="lastIcon || appConfig.ui.icons.chevronDoubleRight" :to=" to?.(pageCount)" />
181
+ <UButton :color="color" :variant="variant" :size="size" :icon="lastIcon" :to=" to?.(pageCount)" />
178
182
  </slot>
179
183
  </PaginationLast>
180
184
  </PaginationList>
@@ -0,0 +1,95 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/ui/pin-input'
7
+ import { tv } from '../utils/tv'
8
+ import type { PartialString } from '../types/utils'
9
+
10
+ const appConfigPinInput = _appConfig as AppConfig & { ui: { pinInput: Partial<typeof theme> } }
11
+
12
+ const pinInput = tv({ extend: tv(theme), ...(appConfigPinInput.ui?.pinInput || {}) })
13
+
14
+ type PinInputVariants = VariantProps<typeof pinInput>
15
+
16
+ export interface PinInputProps extends Pick<PinInputRootProps, 'defaultValue' | 'disabled' | 'id' | 'mask' | 'modelValue' | 'name' | 'otp' | 'placeholder' | 'required' | 'type'> {
17
+ /**
18
+ * The element or component this component should render as.
19
+ * @defaultValue 'div'
20
+ */
21
+ as?: any
22
+ color?: PinInputVariants['color']
23
+ variant?: PinInputVariants['variant']
24
+ size?: PinInputVariants['size']
25
+ length?: number | string
26
+ highlight?: boolean
27
+ class?: any
28
+ ui?: PartialString<typeof pinInput.slots>
29
+ }
30
+
31
+ export type PinInputEmits = PinInputRootEmits & {
32
+ change: [payload: Event]
33
+ blur: [payload: Event]
34
+ }
35
+ </script>
36
+
37
+ <script setup lang="ts">
38
+ import { ref, computed } from 'vue'
39
+ import { PinInputInput, PinInputRoot, useForwardPropsEmits } from 'reka-ui'
40
+ import { reactivePick } from '@vueuse/core'
41
+ import { useFormField } from '../composables/useFormField'
42
+ import { looseToNumber } from '../utils'
43
+
44
+ const props = withDefaults(defineProps<PinInputProps>(), {
45
+ type: 'text',
46
+ length: 5
47
+ })
48
+ const emits = defineEmits<PinInputEmits>()
49
+
50
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultValue', 'disabled', 'id', 'mask', 'modelValue', 'name', 'otp', 'placeholder', 'required', 'type'), emits)
51
+ const { emitFormInput, emitFormFocus, emitFormChange, emitFormBlur, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<PinInputProps>(props)
52
+
53
+ const ui = computed(() => pinInput({
54
+ color: color.value,
55
+ variant: props.variant,
56
+ size: size.value,
57
+ highlight: highlight.value
58
+ }))
59
+
60
+ const completed = ref(false)
61
+ function onComplete(value: string[]) {
62
+ // @ts-expect-error - 'target' does not exist in type 'EventInit'
63
+ const event = new Event('change', { target: { value } })
64
+ emits('change', event)
65
+ emitFormChange()
66
+ }
67
+
68
+ function onBlur(event: FocusEvent) {
69
+ if (!event.relatedTarget || completed.value) {
70
+ emits('blur', event)
71
+ emitFormBlur()
72
+ }
73
+ }
74
+ </script>
75
+
76
+ <template>
77
+ <PinInputRoot
78
+ v-bind="{ ...rootProps, ...ariaAttrs }"
79
+ :id="id"
80
+ :name="name"
81
+ :class="ui.root({ class: [props.class, props.ui?.root] })"
82
+ @update:model-value="emitFormInput()"
83
+ @complete="onComplete"
84
+ >
85
+ <PinInputInput
86
+ v-for="(ids, index) in looseToNumber(props.length)"
87
+ :key="ids"
88
+ :index="index"
89
+ :class="ui.base({ class: props.ui?.base })"
90
+ :disabled="disabled"
91
+ @blur="onBlur"
92
+ @focus="emitFormFocus"
93
+ />
94
+ </PinInputRoot>
95
+ </template>