@nuxt/ui 3.0.0-alpha.7 → 3.0.0-alpha.8

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 (243) hide show
  1. package/.nuxt/ui/accordion.ts +20 -0
  2. package/.nuxt/ui/alert.ts +242 -0
  3. package/.nuxt/ui/avatar-group.ts +40 -0
  4. package/.nuxt/ui/avatar.ts +42 -0
  5. package/.nuxt/ui/badge.ts +194 -0
  6. package/.nuxt/ui/breadcrumb.ts +45 -0
  7. package/.nuxt/ui/button-group.ts +16 -0
  8. package/.nuxt/ui/button.ts +344 -0
  9. package/.nuxt/ui/card.ts +8 -0
  10. package/.nuxt/ui/carousel.ts +41 -0
  11. package/.nuxt/ui/checkbox.ts +105 -0
  12. package/.nuxt/ui/chip.ts +67 -0
  13. package/.nuxt/ui/collapsible.ts +6 -0
  14. package/.nuxt/ui/command-palette.ts +40 -0
  15. package/.nuxt/ui/container.ts +3 -0
  16. package/.nuxt/ui/context-menu.ts +198 -0
  17. package/.nuxt/ui/drawer.ts +55 -0
  18. package/.nuxt/ui/dropdown-menu.ts +199 -0
  19. package/.nuxt/ui/form-field.ts +40 -0
  20. package/.nuxt/ui/form.ts +3 -0
  21. package/.nuxt/ui/index.ts +43 -0
  22. package/.nuxt/ui/input-menu.ts +411 -0
  23. package/.nuxt/ui/input.ts +263 -0
  24. package/.nuxt/ui/kbd.ts +19 -0
  25. package/.nuxt/ui/link.ts +15 -0
  26. package/.nuxt/ui/modal.ts +28 -0
  27. package/.nuxt/ui/navigation-menu.ts +390 -0
  28. package/.nuxt/ui/pagination.ts +8 -0
  29. package/.nuxt/ui/popover.ts +6 -0
  30. package/.nuxt/ui/progress.ts +258 -0
  31. package/.nuxt/ui/radio-group.ts +112 -0
  32. package/.nuxt/ui/select-menu.ts +321 -0
  33. package/.nuxt/ui/select.ts +314 -0
  34. package/.nuxt/ui/separator.ts +143 -0
  35. package/.nuxt/ui/skeleton.ts +3 -0
  36. package/.nuxt/ui/slideover.ts +63 -0
  37. package/.nuxt/ui/slider.ts +148 -0
  38. package/.nuxt/ui/switch.ts +113 -0
  39. package/.nuxt/ui/table.ts +128 -0
  40. package/.nuxt/ui/tabs.ts +227 -0
  41. package/.nuxt/ui/textarea.ts +263 -0
  42. package/.nuxt/ui/toast.ts +66 -0
  43. package/.nuxt/ui/toaster.ts +75 -0
  44. package/.nuxt/ui/tooltip.ts +9 -0
  45. package/cli/templates.mjs +1 -1
  46. package/dist/chunks/component-meta.cjs +73264 -0
  47. package/dist/chunks/component-meta.mjs +73262 -0
  48. package/dist/client/devtools/200.html +1 -0
  49. package/dist/client/devtools/404.html +1 -0
  50. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKK58UfivUw4aw-SK92LTmKP0.woff2 +0 -0
  51. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKy58UfivUw-9uYm8d48E4.woff2 +0 -0
  52. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2 +0 -0
  53. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu6-K6z9mXgjU0-EkYdMs3MAX.woff2 +0 -0
  54. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-7DW3w-R7n06NbhGy.woff +0 -0
  55. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDG3w-leGNfkTmsj.woff +0 -0
  56. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDW3w-ciElMF03ku.woff +0 -0
  57. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JCm3w-sB722Uoa0f.woff +0 -0
  58. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JDW3w-PBDI1JDjwV.woff +0 -0
  59. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8gCm3w-0q1hqVn09O.woff +0 -0
  60. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff +0 -0
  61. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9uCm3w-5TKCIs6EEw.woff +0 -0
  62. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat_XDW3w-r2swRDGfn2.woff +0 -0
  63. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAC5thTQ-ldB60l5U8r.woff +0 -0
  64. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpthTQ-wbFKGFDrgo.woff +0 -0
  65. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpxhTQ-LLUBv5jskj.woff +0 -0
  66. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTQ-F71RdTRbNg.woff +0 -0
  67. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwA_JxhTQ-6nh65gZkc0.woff +0 -0
  68. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTQ-aMoWEJLmTt.woff +0 -0
  69. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTQ-WMBvmLOgKm.woff +0 -0
  70. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAop1hTQ-utGC2hnWq2.woff +0 -0
  71. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTQ-YpyTieVa5B.woff +0 -0
  72. package/dist/client/devtools/_nuxt/Bj9hdafK.js +1 -0
  73. package/dist/client/devtools/_nuxt/DM3_wAgz.js +62 -0
  74. package/dist/client/devtools/_nuxt/builds/latest.json +1 -0
  75. package/dist/client/devtools/_nuxt/builds/meta/e6b425f7-b919-4014-915b-0ea07c316790.json +1 -0
  76. package/dist/client/devtools/_nuxt/entry.DaJP-ZMB.css +24 -0
  77. package/dist/client/devtools/_nuxt/error-404.B0Nmv3fV.css +1 -0
  78. package/dist/client/devtools/_nuxt/error-500.C8fgTxVz.css +1 -0
  79. package/dist/client/devtools/_nuxt/hKiujHsR.js +1 -0
  80. package/dist/client/devtools/favicon.svg +1 -0
  81. package/dist/client/devtools/index.html +1 -0
  82. package/dist/devtools/runtime/DevtoolsRenderer.vue +53 -0
  83. package/dist/devtools/runtime/examples/AvatarGroupExample.vue +7 -0
  84. package/dist/devtools/runtime/examples/ButtonGroupExample.vue +8 -0
  85. package/dist/devtools/runtime/examples/CardExample.vue +13 -0
  86. package/dist/devtools/runtime/examples/CarouselExample.vue +13 -0
  87. package/dist/devtools/runtime/examples/ChipExample.vue +5 -0
  88. package/dist/devtools/runtime/examples/CollapsibleExample.vue +8 -0
  89. package/dist/devtools/runtime/examples/CommandPaletteExample.vue +29 -0
  90. package/dist/devtools/runtime/examples/ContainerExample.vue +5 -0
  91. package/dist/devtools/runtime/examples/ContextMenuExample.vue +5 -0
  92. package/dist/devtools/runtime/examples/DrawerExample.vue +8 -0
  93. package/dist/devtools/runtime/examples/DropdownMenuExample.vue +5 -0
  94. package/dist/devtools/runtime/examples/FormExample.vue +30 -0
  95. package/dist/devtools/runtime/examples/FormFieldExample.vue +5 -0
  96. package/dist/devtools/runtime/examples/LinkExample.vue +5 -0
  97. package/dist/devtools/runtime/examples/ModalExample.vue +8 -0
  98. package/dist/devtools/runtime/examples/PopoverExample.vue +8 -0
  99. package/dist/devtools/runtime/examples/SkeletonExample.vue +3 -0
  100. package/dist/devtools/runtime/examples/SlideoverExample.vue +8 -0
  101. package/dist/devtools/runtime/examples/ToasterExample.vue +11 -0
  102. package/dist/devtools/runtime/examples/TooltipExample.vue +5 -0
  103. package/dist/module.cjs +222 -4
  104. package/dist/module.d.cts +54 -0
  105. package/dist/module.d.mts +10 -0
  106. package/dist/module.d.ts +10 -0
  107. package/dist/module.json +1 -1
  108. package/dist/module.mjs +157 -2763
  109. package/dist/runtime/components/Accordion.vue +32 -1
  110. package/dist/runtime/components/Alert.vue +4 -0
  111. package/dist/runtime/components/App.vue +8 -0
  112. package/dist/runtime/components/Avatar.vue +23 -5
  113. package/dist/runtime/components/AvatarGroup.vue +3 -0
  114. package/dist/runtime/components/Badge.vue +33 -3
  115. package/dist/runtime/components/Breadcrumb.vue +25 -1
  116. package/dist/runtime/components/Button.vue +6 -1
  117. package/dist/runtime/components/ButtonGroup.vue +4 -1
  118. package/dist/runtime/components/Card.vue +3 -0
  119. package/dist/runtime/components/Carousel.vue +7 -2
  120. package/dist/runtime/components/Checkbox.vue +4 -0
  121. package/dist/runtime/components/Chip.vue +9 -2
  122. package/dist/runtime/components/Collapsible.vue +3 -0
  123. package/dist/runtime/components/CommandPalette.vue +3 -1
  124. package/dist/runtime/components/Container.vue +3 -0
  125. package/dist/runtime/components/ContextMenu.vue +64 -3
  126. package/dist/runtime/components/ContextMenuContent.vue +8 -8
  127. package/dist/runtime/components/Drawer.vue +3 -0
  128. package/dist/runtime/components/DropdownMenu.vue +52 -3
  129. package/dist/runtime/components/DropdownMenuContent.vue +8 -8
  130. package/dist/runtime/components/Form.vue +3 -0
  131. package/dist/runtime/components/FormField.vue +3 -0
  132. package/dist/runtime/components/Input.vue +1 -0
  133. package/dist/runtime/components/InputMenu.vue +23 -12
  134. package/dist/runtime/components/Kbd.vue +2 -0
  135. package/dist/runtime/components/Link.vue +50 -1
  136. package/dist/runtime/components/Modal.vue +3 -0
  137. package/dist/runtime/components/NavigationMenu.vue +91 -44
  138. package/dist/runtime/components/Pagination.vue +5 -1
  139. package/dist/runtime/components/Popover.vue +3 -0
  140. package/dist/runtime/components/Progress.vue +1 -1
  141. package/dist/runtime/components/RadioGroup.vue +4 -1
  142. package/dist/runtime/components/Select.vue +24 -13
  143. package/dist/runtime/components/SelectMenu.vue +29 -17
  144. package/dist/runtime/components/Separator.vue +1 -1
  145. package/dist/runtime/components/Skeleton.vue +3 -0
  146. package/dist/runtime/components/Slideover.vue +3 -0
  147. package/dist/runtime/components/Slider.vue +1 -1
  148. package/dist/runtime/components/Switch.vue +5 -1
  149. package/dist/runtime/components/Table.vue +16 -7
  150. package/dist/runtime/components/Tabs.vue +20 -1
  151. package/dist/runtime/components/Toast.vue +4 -0
  152. package/dist/runtime/components/Toaster.vue +7 -0
  153. package/dist/runtime/components/Tooltip.vue +3 -0
  154. package/dist/runtime/composables/defineShortcuts.js +0 -6
  155. package/dist/runtime/composables/extendDevtoolsMeta.d.ts +7 -0
  156. package/dist/runtime/composables/extendDevtoolsMeta.js +2 -0
  157. package/dist/runtime/composables/useKbd.d.ts +10 -3
  158. package/dist/runtime/composables/useKbd.js +14 -8
  159. package/dist/runtime/types/utils.d.ts +7 -0
  160. package/dist/runtime/utils/index.js +1 -1
  161. package/dist/runtime/utils/link.d.ts +1 -1
  162. package/dist/runtime/vue/components/Icon.vue +15 -0
  163. package/dist/runtime/vue/components/Link.vue +195 -0
  164. package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
  165. package/dist/runtime/vue/plugins/color-mode.js +6 -0
  166. package/dist/runtime/vue/plugins/head.d.ts +4 -0
  167. package/dist/runtime/vue/plugins/head.js +6 -0
  168. package/dist/runtime/vue/stubs.d.ts +15 -0
  169. package/dist/runtime/vue/stubs.js +27 -0
  170. package/dist/shared/ui.BU7wzH0D.cjs +2872 -0
  171. package/dist/shared/ui.BufKhDiD.mjs +2865 -0
  172. package/dist/unplugin.cjs +192 -0
  173. package/dist/unplugin.d.cts +47 -0
  174. package/dist/unplugin.d.mts +47 -0
  175. package/dist/unplugin.d.ts +47 -0
  176. package/dist/unplugin.mjs +181 -0
  177. package/dist/vite.cjs +22 -0
  178. package/dist/vite.d.cts +13 -0
  179. package/dist/vite.d.mts +13 -0
  180. package/dist/vite.d.ts +13 -0
  181. package/dist/vite.mjs +20 -0
  182. package/package.json +68 -30
  183. package/vue-plugin.d.ts +5 -0
  184. package/cli/node_modules/.ignored/citty/LICENSE +0 -36
  185. package/cli/node_modules/.ignored/citty/README.md +0 -134
  186. package/cli/node_modules/.ignored/citty/dist/index.cjs +0 -475
  187. package/cli/node_modules/.ignored/citty/dist/index.d.cts +0 -80
  188. package/cli/node_modules/.ignored/citty/dist/index.d.mts +0 -80
  189. package/cli/node_modules/.ignored/citty/dist/index.d.ts +0 -80
  190. package/cli/node_modules/.ignored/citty/dist/index.mjs +0 -463
  191. package/cli/node_modules/.ignored/citty/package.json +0 -49
  192. package/cli/node_modules/.ignored/consola/LICENSE +0 -47
  193. package/cli/node_modules/.ignored/consola/README.md +0 -318
  194. package/cli/node_modules/.ignored/consola/core.d.ts +0 -1
  195. package/cli/node_modules/.ignored/consola/dist/basic.cjs +0 -32
  196. package/cli/node_modules/.ignored/consola/dist/basic.d.ts +0 -9
  197. package/cli/node_modules/.ignored/consola/dist/basic.mjs +0 -24
  198. package/cli/node_modules/.ignored/consola/dist/browser.cjs +0 -80
  199. package/cli/node_modules/.ignored/consola/dist/browser.d.ts +0 -7
  200. package/cli/node_modules/.ignored/consola/dist/browser.mjs +0 -72
  201. package/cli/node_modules/.ignored/consola/dist/chunks/prompt.cjs +0 -436
  202. package/cli/node_modules/.ignored/consola/dist/chunks/prompt.mjs +0 -429
  203. package/cli/node_modules/.ignored/consola/dist/core.cjs +0 -415
  204. package/cli/node_modules/.ignored/consola/dist/core.d.ts +0 -124
  205. package/cli/node_modules/.ignored/consola/dist/core.mjs +0 -410
  206. package/cli/node_modules/.ignored/consola/dist/index.cjs +0 -21
  207. package/cli/node_modules/.ignored/consola/dist/index.d.ts +0 -9
  208. package/cli/node_modules/.ignored/consola/dist/index.mjs +0 -8
  209. package/cli/node_modules/.ignored/consola/dist/shared/consola.06ad8a64.mjs +0 -62
  210. package/cli/node_modules/.ignored/consola/dist/shared/consola.36c0034f.mjs +0 -636
  211. package/cli/node_modules/.ignored/consola/dist/shared/consola.4bbae468.cjs +0 -645
  212. package/cli/node_modules/.ignored/consola/dist/shared/consola.deac7d5a.cjs +0 -65
  213. package/cli/node_modules/.ignored/consola/dist/utils.cjs +0 -308
  214. package/cli/node_modules/.ignored/consola/dist/utils.d.ts +0 -169
  215. package/cli/node_modules/.ignored/consola/dist/utils.mjs +0 -284
  216. package/cli/node_modules/.ignored/consola/lib/index.cjs +0 -9
  217. package/cli/node_modules/.ignored/consola/package.json +0 -101
  218. package/cli/node_modules/.ignored/consola/utils.d.ts +0 -1
  219. package/cli/node_modules/.ignored/pathe/LICENSE +0 -44
  220. package/cli/node_modules/.ignored/pathe/README.md +0 -69
  221. package/cli/node_modules/.ignored/pathe/dist/index.cjs +0 -23
  222. package/cli/node_modules/.ignored/pathe/dist/index.d.cts +0 -36
  223. package/cli/node_modules/.ignored/pathe/dist/index.d.mts +0 -36
  224. package/cli/node_modules/.ignored/pathe/dist/index.d.ts +0 -36
  225. package/cli/node_modules/.ignored/pathe/dist/index.mjs +0 -1
  226. package/cli/node_modules/.ignored/pathe/dist/shared/pathe.1f0a373c.cjs +0 -238
  227. package/cli/node_modules/.ignored/pathe/dist/shared/pathe.ff20891b.mjs +0 -221
  228. package/cli/node_modules/.ignored/pathe/dist/utils.cjs +0 -58
  229. package/cli/node_modules/.ignored/pathe/dist/utils.d.cts +0 -5
  230. package/cli/node_modules/.ignored/pathe/dist/utils.d.mts +0 -5
  231. package/cli/node_modules/.ignored/pathe/dist/utils.d.ts +0 -5
  232. package/cli/node_modules/.ignored/pathe/dist/utils.mjs +0 -54
  233. package/cli/node_modules/.ignored/pathe/package.json +0 -48
  234. package/cli/node_modules/.ignored/pathe/utils.d.ts +0 -1
  235. package/cli/node_modules/.ignored/scule/LICENSE +0 -21
  236. package/cli/node_modules/.ignored/scule/README.md +0 -149
  237. package/cli/node_modules/.ignored/scule/dist/index.cjs +0 -92
  238. package/cli/node_modules/.ignored/scule/dist/index.d.cts +0 -57
  239. package/cli/node_modules/.ignored/scule/dist/index.d.mts +0 -57
  240. package/cli/node_modules/.ignored/scule/dist/index.d.ts +0 -57
  241. package/cli/node_modules/.ignored/scule/dist/index.mjs +0 -80
  242. package/cli/node_modules/.ignored/scule/package.json +0 -43
  243. package/cli/node_modules/.package-lock.json +0 -33
@@ -1,23 +1,20 @@
1
- <!-- eslint-disable vue/block-tag-newline -->
2
1
  <script lang="ts">
3
2
  import { tv, type VariantProps } from 'tailwind-variants'
4
3
  import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps } from 'radix-vue'
5
4
  import type { AppConfig } from '@nuxt/schema'
6
5
  import _appConfig from '#build/app.config'
7
6
  import theme from '#build/ui/navigation-menu'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
8
  import type { AvatarProps, BadgeProps, LinkProps } from '../types'
9
- import type { DynamicSlots, PartialString } from '../types/utils'
9
+ import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString } from '../types/utils'
10
10
 
11
11
  const appConfig = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
12
12
 
13
13
  const navigationMenu = tv({ extend: tv(theme), ...(appConfig.ui?.navigationMenu || {}) })
14
14
 
15
- export interface NavigationMenuChildItem extends Omit<LinkProps, 'raw' | 'custom'> {
16
- label: string
15
+ export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'children'> {
16
+ /** Description is only used when `orientation` is `horizontal`. */
17
17
  description?: string
18
- icon?: string
19
- badge?: string | number | BadgeProps
20
- onSelect?(e: Event): void
21
18
  }
22
19
 
23
20
  export interface NavigationMenuItem extends Omit<LinkProps, 'raw' | 'custom'> {
@@ -37,7 +34,7 @@ type NavigationMenuVariants = VariantProps<typeof navigationMenu>
37
34
  export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'modelValue' | 'skipDelayDuration'> {
38
35
  /**
39
36
  * The element or component this component should render as.
40
- * @defaultValue `div`
37
+ * @defaultValue 'div'
41
38
  */
42
39
  as?: any
43
40
  /**
@@ -45,7 +42,7 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'd
45
42
  * @defaultValue appConfig.ui.icons.chevronDown
46
43
  */
47
44
  trailingIcon?: string
48
- items?: T[] | T[][]
45
+ items?: T
49
46
  color?: NavigationMenuVariants['color']
50
47
  variant?: NavigationMenuVariants['variant']
51
48
  /**
@@ -81,14 +78,53 @@ export type NavigationMenuSlots<T extends { slot?: string }> = {
81
78
  'item-leading': SlotProps<T>
82
79
  'item-label': SlotProps<T>
83
80
  'item-trailing': SlotProps<T>
81
+ 'item-content': SlotProps<T>
84
82
  } & DynamicSlots<T, SlotProps<T>>
85
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
+ })
86
122
  </script>
87
123
 
88
- <script setup lang="ts" generic="T extends NavigationMenuItem">
89
- import { computed, toRef } from 'vue'
124
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<NavigationMenuItem>">
125
+ import { computed, reactive, toRef } from 'vue'
90
126
  import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, useForwardPropsEmits } from 'radix-vue'
91
- import { reactivePick, createReusableTemplate } from '@vueuse/core'
127
+ import { createReusableTemplate } from '@vueuse/core'
92
128
  import { get } from '../utils'
93
129
  import { pickLinkProps } from '../utils/link'
94
130
  import ULinkBase from './LinkBase.vue'
@@ -98,7 +134,7 @@ import UIcon from './Icon.vue'
98
134
  import UBadge from './Badge.vue'
99
135
  import UCollapsible from './Collapsible.vue'
100
136
 
101
- const props = withDefaults(defineProps<NavigationMenuProps<T>>(), {
137
+ const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
102
138
  orientation: 'horizontal',
103
139
  delayDuration: 0,
104
140
  labelKey: 'label'
@@ -106,7 +142,15 @@ const props = withDefaults(defineProps<NavigationMenuProps<T>>(), {
106
142
  const emits = defineEmits<NavigationMenuEmits>()
107
143
  const slots = defineSlots<NavigationMenuSlots<T>>()
108
144
 
109
- const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'delayDuration', 'skipDelayDuration', 'orientation'), emits)
145
+ const rootProps = useForwardPropsEmits(reactive({
146
+ as: props.as,
147
+ modelValue: props.modelValue,
148
+ defaultValue: props.defaultValue,
149
+ delayDuration: props.delayDuration,
150
+ skipDelayDuration: props.skipDelayDuration,
151
+ orientation: props.orientation
152
+ }), emits)
153
+
110
154
  const contentProps = toRef(() => props.content)
111
155
 
112
156
  const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, active?: boolean, index: number }>()
@@ -148,13 +192,14 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
148
192
  v-bind="(typeof item.badge === 'string' || typeof item.badge === 'number') ? { label: item.badge } : item.badge"
149
193
  :class="ui.linkTrailingBadge({ class: props.ui?.linkTrailingBadge })"
150
194
  />
151
- <UIcon v-if="item.children?.length" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
195
+
196
+ <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 })" />
152
197
  </slot>
153
198
  </span>
154
199
  </slot>
155
200
  </DefineItemTemplate>
156
201
 
157
- <NavigationMenuRoot v-bind="rootProps" :class="ui.root({ class: [props.class, props.ui?.root] })">
202
+ <NavigationMenuRoot v-bind="rootProps" :data-orientation="orientation" :class="ui.root({ class: [props.class, props.ui?.root] })">
158
203
  <template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
159
204
  <NavigationMenuList :class="ui.list({ class: props.ui?.list })">
160
205
  <component
@@ -167,50 +212,52 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
167
212
  >
168
213
  <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
169
214
  <component
170
- :is="(item.children?.length && orientation === 'horizontal') ? NavigationMenuTrigger : NavigationMenuLink"
171
- v-bind="item.children?.length ? { disabled: item.disabled } : { active }"
215
+ :is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
172
216
  as-child
173
217
  :active="active"
218
+ :disabled="item.disabled"
174
219
  @select="item.onSelect"
175
220
  >
176
221
  <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active, disabled: !!item.disabled })">
177
- <ReuseItemTemplate :item="item" :active="active" :index="index" />
222
+ <ReuseItemTemplate :item="(item as T)" :active="active" :index="index" />
178
223
  </ULinkBase>
179
224
  </component>
180
225
 
181
- <NavigationMenuContent v-if="item.children?.length && orientation === 'horizontal'" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
182
- <ul :class="ui.childList({ class: props.ui?.childList })">
183
- <li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
184
- <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
185
- <NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
186
- <ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
187
- <UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />
188
-
189
- <div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
190
- <p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
191
- {{ get(childItem, props.labelKey as string) }}
192
-
193
- <UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
194
- </p>
195
- <p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
196
- {{ childItem.description }}
197
- </p>
198
- </div>
199
- </ULinkBase>
200
- </NavigationMenuLink>
201
- </ULink>
202
- </li>
203
- </ul>
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>
204
251
  </NavigationMenuContent>
205
252
  </ULink>
206
253
 
207
- <template v-if="item.children?.length && orientation === 'vertical'" #content>
254
+ <template v-if="orientation === 'vertical' && item.children?.length" #content>
208
255
  <ul :class="ui.childList({ class: props.ui?.childList })">
209
256
  <li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
210
257
  <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
211
258
  <NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
212
259
  <ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled })">
213
- <ReuseItemTemplate :item="childItem" :active="childActive" :index="childIndex" />
260
+ <ReuseItemTemplate :item="(childItem as T)" :active="childActive" :index="childIndex" />
214
261
  </ULinkBase>
215
262
  </NavigationMenuLink>
216
263
  </ULink>
@@ -5,6 +5,7 @@ import type { AppConfig } from '@nuxt/schema'
5
5
  import type { RouteLocationRaw } from '#vue-router'
6
6
  import _appConfig from '#build/app.config'
7
7
  import theme from '#build/ui/pagination'
8
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
9
  import type { ButtonProps } from '../types'
9
10
 
10
11
  const appConfig = _appConfig as AppConfig & { ui: { pagination: Partial<typeof theme> } }
@@ -14,7 +15,7 @@ const pagination = tv({ extend: tv(theme), ...(appConfig.ui?.pagination || {}) }
14
15
  export interface PaginationProps extends Pick<PaginationRootProps, 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'> {
15
16
  /**
16
17
  * The element or component this component should render as.
17
- * @defaultValue `div`
18
+ * @defaultValue 'div'
18
19
  */
19
20
  as?: any
20
21
  /**
@@ -97,12 +98,15 @@ export interface PaginationSlots {
97
98
  index: number
98
99
  }): any
99
100
  }
101
+
102
+ extendDevtoolsMeta({ defaultProps: { total: 50 } })
100
103
  </script>
101
104
 
102
105
  <script setup lang="ts">
103
106
  import { PaginationRoot, PaginationList, PaginationListItem, PaginationFirst, PaginationPrev, PaginationEllipsis, PaginationNext, PaginationLast, useForwardPropsEmits } from 'radix-vue'
104
107
  import { reactivePick } from '@vueuse/core'
105
108
  import { useAppConfig } from '#imports'
109
+ import UButton from './Button.vue'
106
110
 
107
111
  const props = withDefaults(defineProps<PaginationProps>(), {
108
112
  size: 'md',
@@ -4,6 +4,7 @@ import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverCon
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/popover'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
 
8
9
  const appConfig = _appConfig as AppConfig & { ui: { popover: Partial<typeof theme> } }
9
10
 
@@ -40,6 +41,8 @@ export interface PopoverSlots {
40
41
  default(props: { open: boolean }): any
41
42
  content(props?: {}): any
42
43
  }
44
+
45
+ extendDevtoolsMeta({ example: 'PopoverExample' })
43
46
  </script>
44
47
 
45
48
  <script setup lang="ts">
@@ -15,7 +15,7 @@ type ProgressVariants = VariantProps<typeof progress>
15
15
  export interface ProgressProps extends Pick<ProgressRootProps, 'getValueLabel' | 'modelValue'> {
16
16
  /**
17
17
  * The element or component this component should render as.
18
- * @defaultValue `div`
18
+ * @defaultValue 'div'
19
19
  */
20
20
  as?: any
21
21
  /** The maximum progress value. */
@@ -4,6 +4,7 @@ import type { RadioGroupRootProps, RadioGroupRootEmits } from 'radix-vue'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/radio-group'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
  import type { AcceptableValue } from '../types/utils'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { radioGroup: Partial<typeof theme> } }
@@ -22,7 +23,7 @@ export interface RadioGroupItem {
22
23
  export interface RadioGroupProps<T> extends Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
23
24
  /**
24
25
  * The element or component this component should render as.
25
- * @defaultValue `div`
26
+ * @defaultValue 'div'
26
27
  */
27
28
  as?: any
28
29
  legend?: string
@@ -64,6 +65,8 @@ export interface RadioGroupSlots<T> {
64
65
  label: SlotProps<T>
65
66
  description: SlotProps<T>
66
67
  }
68
+
69
+ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
67
70
  </script>
68
71
 
69
72
  <script setup lang="ts" generic="T extends RadioGroupItem | AcceptableValue">
@@ -5,8 +5,9 @@ import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/select'
7
7
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
9
  import type { AvatarProps, ChipProps, InputProps } from '../types'
9
- import type { AcceptableValue, PartialString } from '../types/utils'
10
+ import type { AcceptableValue, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
10
11
 
11
12
  const appConfig = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
12
13
 
@@ -28,7 +29,7 @@ export interface SelectItem {
28
29
 
29
30
  type SelectVariants = VariantProps<typeof select>
30
31
 
31
- export interface SelectProps<T> extends Omit<SelectRootProps, 'dir'>, UseComponentIconsProps {
32
+ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue> = MaybeArrayOfArray<SelectItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined> extends Omit<SelectRootProps, 'dir' | 'modelValue'>, UseComponentIconsProps {
32
33
  id?: string
33
34
  /** The placeholder text when the select is empty. */
34
35
  placeholder?: string
@@ -64,24 +65,26 @@ export interface SelectProps<T> extends Omit<SelectRootProps, 'dir'>, UseCompone
64
65
  * When `items` is an array of objects, select the field to use as the value.
65
66
  * @defaultValue 'value'
66
67
  */
67
- valueKey?: string
68
+ valueKey?: V
68
69
  /**
69
70
  * When `items` is an array of objects, select the field to use as the label.
70
71
  * @defaultValue 'label'
71
72
  */
72
- labelKey?: string
73
- items?: T[] | T[][]
73
+ labelKey?: SelectItemKey<T>
74
+ items?: I
74
75
  /** Highlight the ring color like a focus state. */
75
76
  highlight?: boolean
76
77
  class?: any
77
78
  ui?: PartialString<typeof select.slots>
79
+ /** The controlled value of the Select. Can be bind as `v-model`. */
80
+ modelValue?: SelectModelValue<T, V, false, T extends { value: infer U } ? U : never>
78
81
  }
79
82
 
80
- export type SelectEmits = SelectRootEmits & {
83
+ export type SelectEmits<T, V> = Omit<SelectRootEmits, 'update:modelValue'> & {
81
84
  change: [payload: Event]
82
85
  blur: [payload: FocusEvent]
83
86
  focus: [payload: FocusEvent]
84
- }
87
+ } & SelectModelValueEmits<T, V, false, T extends { value: infer U } ? U : never>
85
88
 
86
89
  type SlotProps<T> = (props: { item: T, index: number }) => any
87
90
 
@@ -93,11 +96,13 @@ export interface SelectSlots<T> {
93
96
  'item-label': SlotProps<T>
94
97
  'item-trailing': SlotProps<T>
95
98
  }
99
+
100
+ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
96
101
  </script>
97
102
 
98
- <script setup lang="ts" generic="T extends SelectItem | AcceptableValue">
103
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue> = MaybeArrayOfArray<SelectItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined">
99
104
  import { computed, toRef } from 'vue'
100
- import { SelectRoot, SelectTrigger, SelectValue, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from 'radix-vue'
105
+ import { SelectRoot, SelectArrow, SelectTrigger, SelectValue, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from 'radix-vue'
101
106
  import { defu } from 'defu'
102
107
  import { reactivePick } from '@vueuse/core'
103
108
  import { useAppConfig } from '#imports'
@@ -109,17 +114,18 @@ import UIcon from './Icon.vue'
109
114
  import UAvatar from './Avatar.vue'
110
115
  import UChip from './Chip.vue'
111
116
 
112
- const props = withDefaults(defineProps<SelectProps<T>>(), {
113
- valueKey: 'value',
114
- labelKey: 'label',
117
+ const props = withDefaults(defineProps<SelectProps<T, I, V>>(), {
118
+ valueKey: 'value' as never,
119
+ labelKey: 'label' as never,
115
120
  portal: true
116
121
  })
117
- const emits = defineEmits<SelectEmits>()
122
+ const emits = defineEmits<SelectEmits<T, V>>()
118
123
  const slots = defineSlots<SelectSlots<T>>()
119
124
 
120
125
  const appConfig = useAppConfig()
121
126
  const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required'), emits)
122
127
  const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as SelectContentProps)
128
+ const arrowProps = toRef(() => props.arrow as SelectArrowProps)
123
129
 
124
130
  const { emitFormChange, emitFormInput, emitFormBlur, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
125
131
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
@@ -166,6 +172,9 @@ function onUpdateOpen(value: boolean) {
166
172
  v-slot="{ modelValue, open }"
167
173
  v-bind="rootProps"
168
174
  :name="name"
175
+ :default-value="(defaultValue as string)"
176
+ :model-value="(modelValue as string)"
177
+ :autocomplete="autocomplete"
169
178
  :disabled="disabled"
170
179
  @update:model-value="onUpdate"
171
180
  @update:open="onUpdateOpen"
@@ -236,6 +245,8 @@ function onUpdateOpen(value: boolean) {
236
245
  </template>
237
246
  </SelectGroup>
238
247
  </SelectViewport>
248
+
249
+ <SelectArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
239
250
  </SelectContent>
240
251
  </SelectPortal>
241
252
  </SelectRoot>
@@ -5,8 +5,9 @@ import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/select-menu'
7
7
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
9
  import type { AvatarProps, ChipProps, InputProps } from '../types'
9
- import type { AcceptableValue, ArrayOrWrapped, PartialString } from '../types/utils'
10
+ import type { AcceptableValue, ArrayOrWrapped, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
10
11
 
11
12
  const appConfig = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
12
13
 
@@ -28,7 +29,7 @@ export interface SelectMenuItem {
28
29
 
29
30
  type SelectMenuVariants = VariantProps<typeof selectMenu>
30
31
 
31
- export interface SelectMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValue' | 'defaultValue' | 'selectedValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'multiple' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
32
+ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'defaultValue' | 'selectedValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
32
33
  id?: string
33
34
  /** The placeholder text when the select is empty. */
34
35
  placeholder?: string
@@ -77,24 +78,28 @@ export interface SelectMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelVal
77
78
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
78
79
  * @defaultValue undefined
79
80
  */
80
- valueKey?: keyof T
81
+ valueKey?: V
81
82
  /**
82
83
  * When `items` is an array of objects, select the field to use as the label.
83
84
  * @defaultValue 'label'
84
85
  */
85
- labelKey?: keyof T
86
- items?: T[] | T[][]
86
+ labelKey?: SelectItemKey<T>
87
+ items?: I
87
88
  /** Highlight the ring color like a focus state. */
88
89
  highlight?: boolean
89
90
  class?: any
90
91
  ui?: PartialString<typeof selectMenu.slots>
92
+ /** The controlled value of the Combobox. Can be binded-with with `v-model`. */
93
+ modelValue?: SelectModelValue<T, V, M>
94
+ /** Whether multiple options can be selected or not. */
95
+ multiple?: M
91
96
  }
92
97
 
93
- export type SelectMenuEmits<T> = ComboboxRootEmits<T> & {
98
+ export type SelectMenuEmits<T, V, M extends boolean> = Omit<ComboboxRootEmits<T>, 'update:modelValue'> & {
94
99
  change: [payload: Event]
95
100
  blur: [payload: FocusEvent]
96
101
  focus: [payload: FocusEvent]
97
- }
102
+ } & SelectModelValueEmits<T, V, M>
98
103
 
99
104
  type SlotProps<T> = (props: { item: T, index: number }) => any
100
105
 
@@ -108,13 +113,15 @@ export interface SelectMenuSlots<T> {
108
113
  'item-label': SlotProps<T>
109
114
  'item-trailing': SlotProps<T>
110
115
  }
116
+
117
+ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
111
118
  </script>
112
119
 
113
- <script setup lang="ts" generic="T extends SelectMenuItem | AcceptableValue">
120
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
114
121
  import { computed, toRef } from 'vue'
115
- import { ComboboxRoot, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, useForwardPropsEmits } from 'radix-vue'
122
+ import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, useForwardPropsEmits } from 'radix-vue'
116
123
  import { defu } from 'defu'
117
- import isEqual from 'fast-deep-equal'
124
+ import * as isEqual from 'fast-deep-equal'
118
125
  import { reactivePick } from '@vueuse/core'
119
126
  import { useAppConfig } from '#imports'
120
127
  import { useButtonGroup } from '../composables/useButtonGroup'
@@ -125,15 +132,16 @@ import UIcon from './Icon.vue'
125
132
  import UAvatar from './Avatar.vue'
126
133
  import UChip from './Chip.vue'
127
134
 
128
- const props = withDefaults(defineProps<SelectMenuProps<T>>(), {
135
+ const props = withDefaults(defineProps<SelectMenuProps<T, I, V, M>>(), {
129
136
  search: true,
130
137
  portal: true,
131
138
  autofocusDelay: 0,
132
139
  searchInput: () => ({ placeholder: 'Search...' }),
133
140
  filter: () => ['label'],
134
- labelKey: 'label' as keyof T
141
+ labelKey: 'label' as never
135
142
  })
136
- const emits = defineEmits<SelectMenuEmits<T>>()
143
+
144
+ const emits = defineEmits<SelectMenuEmits<T, V, M>>()
137
145
  const slots = defineSlots<SelectMenuSlots<T>>()
138
146
 
139
147
  const searchTerm = defineModel<string>('searchTerm', { default: '' })
@@ -141,6 +149,8 @@ const searchTerm = defineModel<string>('searchTerm', { default: '' })
141
149
  const appConfig = useAppConfig()
142
150
  const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits)
143
151
  const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
152
+ const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
153
+
144
154
  const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
145
155
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
146
156
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
@@ -158,17 +168,17 @@ const ui = computed(() => selectMenu({
158
168
  buttonGroup: orientation.value
159
169
  }))
160
170
 
161
- function displayValue(value: T): string {
171
+ function displayValue(value: T | T[]): string {
162
172
  if (props.multiple && Array.isArray(value)) {
163
173
  return value.map(v => displayValue(v)).join(', ')
164
174
  }
165
175
 
166
- const item = items.value.find(item => props.valueKey ? isEqual(get(item as Record<string, any>, props.valueKey as string), value) : isEqual(item, value))
176
+ const item = items.value.find(item => props.valueKey ? isEqual.default(get(item as Record<string, any>, props.valueKey as string), value) : isEqual.default(item, value))
167
177
 
168
178
  return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
169
179
  }
170
180
 
171
- function filterFunction(items: ArrayOrWrapped<AcceptableValue>, searchTerm: string): ArrayOrWrapped<AcceptableValue> {
181
+ function filterFunction(items: ArrayOrWrapped<T>, searchTerm: string): ArrayOrWrapped<T> {
172
182
  if (props.filter === false) {
173
183
  return items
174
184
  }
@@ -176,7 +186,7 @@ function filterFunction(items: ArrayOrWrapped<AcceptableValue>, searchTerm: stri
176
186
  const fields = Array.isArray(props.filter) ? props.filter : [props.labelKey]
177
187
  const escapedSearchTerm = escapeRegExp(searchTerm)
178
188
 
179
- return items.filter((item) => {
189
+ return items.filter((item: T) => {
180
190
  if (typeof item !== 'object') {
181
191
  return String(item).search(new RegExp(escapedSearchTerm, 'i')) !== -1
182
192
  }
@@ -319,6 +329,8 @@ function onUpdateOpen(value: boolean) {
319
329
  </template>
320
330
  </ComboboxGroup>
321
331
  </ComboboxViewport>
332
+
333
+ <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
322
334
  </ComboboxContent>
323
335
  </ComboboxPortal>
324
336
  </ComboboxRoot>
@@ -15,7 +15,7 @@ type SeparatorVariants = VariantProps<typeof separator>
15
15
  export interface SeparatorProps extends Pick<_SeparatorProps, 'decorative'> {
16
16
  /**
17
17
  * The element or component this component should render as.
18
- * @defaultValue `div`
18
+ * @defaultValue 'div'
19
19
  */
20
20
  as?: any
21
21
  /** Display a label in the middle. */
@@ -3,6 +3,7 @@ import { tv } from 'tailwind-variants'
3
3
  import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/ui/skeleton'
6
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
6
7
 
7
8
  const appConfig = _appConfig as AppConfig & { ui: { skeleton: Partial<typeof theme> } }
8
9
 
@@ -16,6 +17,8 @@ export interface SkeletonProps {
16
17
  as?: any
17
18
  class?: any
18
19
  }
20
+
21
+ extendDevtoolsMeta({ example: 'SkeletonExample' })
19
22
  </script>
20
23
 
21
24
  <script setup lang="ts">
@@ -4,6 +4,7 @@ import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'radix
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/slideover'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
  import type { ButtonProps } from '../types'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { slideover: Partial<typeof theme> } }
@@ -65,6 +66,8 @@ export interface SlideoverSlots {
65
66
  body(props?: {}): any
66
67
  footer(props?: {}): any
67
68
  }
69
+
70
+ extendDevtoolsMeta({ example: 'SlideoverExample' })
68
71
  </script>
69
72
 
70
73
  <script setup lang="ts">
@@ -14,7 +14,7 @@ type SliderVariants = VariantProps<typeof slider>
14
14
  export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'> {
15
15
  /**
16
16
  * The element or component this component should render as.
17
- * @defaultValue `div`
17
+ * @defaultValue 'div'
18
18
  */
19
19
  as?: any
20
20
  size?: SliderVariants['size']