@nuxt/ui 3.0.0-alpha.6 → 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 (257) 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 +16 -6
  106. package/dist/module.d.ts +16 -6
  107. package/dist/module.json +1 -1
  108. package/dist/module.mjs +157 -2629
  109. package/dist/runtime/components/Accordion.vue +45 -6
  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 +39 -7
  116. package/dist/runtime/components/Button.vue +10 -3
  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 +13 -8
  120. package/dist/runtime/components/Checkbox.vue +7 -6
  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 +28 -17
  124. package/dist/runtime/components/Container.vue +3 -0
  125. package/dist/runtime/components/ContextMenu.vue +95 -10
  126. package/dist/runtime/components/ContextMenuContent.vue +41 -13
  127. package/dist/runtime/components/Drawer.vue +3 -0
  128. package/dist/runtime/components/DropdownMenu.vue +83 -10
  129. package/dist/runtime/components/DropdownMenuContent.vue +43 -13
  130. package/dist/runtime/components/Form.vue +6 -1
  131. package/dist/runtime/components/FormField.vue +3 -0
  132. package/dist/runtime/components/Input.vue +7 -4
  133. package/dist/runtime/components/InputMenu.vue +61 -34
  134. package/dist/runtime/components/Kbd.vue +2 -0
  135. package/dist/runtime/components/Link.vue +50 -1
  136. package/dist/runtime/components/LinkBase.vue +4 -2
  137. package/dist/runtime/components/Modal.vue +3 -0
  138. package/dist/runtime/components/NavigationMenu.vue +159 -75
  139. package/dist/runtime/components/Pagination.vue +5 -1
  140. package/dist/runtime/components/Popover.vue +3 -0
  141. package/dist/runtime/components/Progress.vue +1 -1
  142. package/dist/runtime/components/RadioGroup.vue +26 -4
  143. package/dist/runtime/components/Select.vue +44 -21
  144. package/dist/runtime/components/SelectMenu.vue +67 -43
  145. package/dist/runtime/components/Separator.vue +1 -1
  146. package/dist/runtime/components/Skeleton.vue +3 -0
  147. package/dist/runtime/components/Slideover.vue +3 -0
  148. package/dist/runtime/components/Slider.vue +1 -1
  149. package/dist/runtime/components/Switch.vue +5 -1
  150. package/dist/runtime/components/Table.vue +241 -0
  151. package/dist/runtime/components/Tabs.vue +35 -8
  152. package/dist/runtime/components/Toast.vue +4 -0
  153. package/dist/runtime/components/Toaster.vue +8 -1
  154. package/dist/runtime/components/Tooltip.vue +3 -0
  155. package/dist/runtime/composables/defineShortcuts.js +1 -7
  156. package/dist/runtime/composables/extendDevtoolsMeta.d.ts +7 -0
  157. package/dist/runtime/composables/extendDevtoolsMeta.js +2 -0
  158. package/dist/runtime/composables/useComponentIcons.d.ts +3 -0
  159. package/dist/runtime/composables/useKbd.d.ts +10 -3
  160. package/dist/runtime/composables/useKbd.js +14 -8
  161. package/dist/runtime/composables/useModal.d.ts +1 -1
  162. package/dist/runtime/composables/useSlideover.d.ts +1 -1
  163. package/dist/runtime/index.css +1 -1
  164. package/dist/runtime/keyframes.css +1 -0
  165. package/dist/runtime/types/form.d.ts +2 -1
  166. package/dist/runtime/types/index.d.ts +1 -0
  167. package/dist/runtime/types/index.js +1 -0
  168. package/dist/runtime/types/utils.d.ts +7 -0
  169. package/dist/runtime/utils/form.d.ts +3 -0
  170. package/dist/runtime/utils/form.js +14 -0
  171. package/dist/runtime/utils/index.d.ts +1 -0
  172. package/dist/runtime/utils/index.js +3 -0
  173. package/dist/runtime/utils/link.d.ts +1 -1
  174. package/dist/runtime/vue/components/Icon.vue +15 -0
  175. package/dist/runtime/vue/components/Link.vue +195 -0
  176. package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
  177. package/dist/runtime/vue/plugins/color-mode.js +6 -0
  178. package/dist/runtime/vue/plugins/head.d.ts +4 -0
  179. package/dist/runtime/vue/plugins/head.js +6 -0
  180. package/dist/runtime/vue/stubs.d.ts +15 -0
  181. package/dist/runtime/vue/stubs.js +27 -0
  182. package/dist/shared/ui.BU7wzH0D.cjs +2872 -0
  183. package/dist/shared/ui.BufKhDiD.mjs +2865 -0
  184. package/dist/unplugin.cjs +192 -0
  185. package/dist/unplugin.d.cts +47 -0
  186. package/dist/unplugin.d.mts +47 -0
  187. package/dist/unplugin.d.ts +47 -0
  188. package/dist/unplugin.mjs +181 -0
  189. package/dist/vite.cjs +22 -0
  190. package/dist/vite.d.cts +13 -0
  191. package/dist/vite.d.mts +13 -0
  192. package/dist/vite.d.ts +13 -0
  193. package/dist/vite.mjs +20 -0
  194. package/package.json +73 -32
  195. package/vue-plugin.d.ts +5 -0
  196. package/cli/node_modules/.ignored/citty/LICENSE +0 -36
  197. package/cli/node_modules/.ignored/citty/README.md +0 -134
  198. package/cli/node_modules/.ignored/citty/dist/index.cjs +0 -475
  199. package/cli/node_modules/.ignored/citty/dist/index.d.cts +0 -80
  200. package/cli/node_modules/.ignored/citty/dist/index.d.mts +0 -80
  201. package/cli/node_modules/.ignored/citty/dist/index.d.ts +0 -80
  202. package/cli/node_modules/.ignored/citty/dist/index.mjs +0 -463
  203. package/cli/node_modules/.ignored/citty/package.json +0 -49
  204. package/cli/node_modules/.ignored/consola/LICENSE +0 -47
  205. package/cli/node_modules/.ignored/consola/README.md +0 -318
  206. package/cli/node_modules/.ignored/consola/core.d.ts +0 -1
  207. package/cli/node_modules/.ignored/consola/dist/basic.cjs +0 -32
  208. package/cli/node_modules/.ignored/consola/dist/basic.d.ts +0 -9
  209. package/cli/node_modules/.ignored/consola/dist/basic.mjs +0 -24
  210. package/cli/node_modules/.ignored/consola/dist/browser.cjs +0 -80
  211. package/cli/node_modules/.ignored/consola/dist/browser.d.ts +0 -7
  212. package/cli/node_modules/.ignored/consola/dist/browser.mjs +0 -72
  213. package/cli/node_modules/.ignored/consola/dist/chunks/prompt.cjs +0 -436
  214. package/cli/node_modules/.ignored/consola/dist/chunks/prompt.mjs +0 -429
  215. package/cli/node_modules/.ignored/consola/dist/core.cjs +0 -415
  216. package/cli/node_modules/.ignored/consola/dist/core.d.ts +0 -124
  217. package/cli/node_modules/.ignored/consola/dist/core.mjs +0 -410
  218. package/cli/node_modules/.ignored/consola/dist/index.cjs +0 -21
  219. package/cli/node_modules/.ignored/consola/dist/index.d.ts +0 -9
  220. package/cli/node_modules/.ignored/consola/dist/index.mjs +0 -8
  221. package/cli/node_modules/.ignored/consola/dist/shared/consola.06ad8a64.mjs +0 -62
  222. package/cli/node_modules/.ignored/consola/dist/shared/consola.36c0034f.mjs +0 -636
  223. package/cli/node_modules/.ignored/consola/dist/shared/consola.4bbae468.cjs +0 -645
  224. package/cli/node_modules/.ignored/consola/dist/shared/consola.deac7d5a.cjs +0 -65
  225. package/cli/node_modules/.ignored/consola/dist/utils.cjs +0 -308
  226. package/cli/node_modules/.ignored/consola/dist/utils.d.ts +0 -169
  227. package/cli/node_modules/.ignored/consola/dist/utils.mjs +0 -284
  228. package/cli/node_modules/.ignored/consola/lib/index.cjs +0 -9
  229. package/cli/node_modules/.ignored/consola/package.json +0 -101
  230. package/cli/node_modules/.ignored/consola/utils.d.ts +0 -1
  231. package/cli/node_modules/.ignored/pathe/LICENSE +0 -44
  232. package/cli/node_modules/.ignored/pathe/README.md +0 -69
  233. package/cli/node_modules/.ignored/pathe/dist/index.cjs +0 -23
  234. package/cli/node_modules/.ignored/pathe/dist/index.d.cts +0 -36
  235. package/cli/node_modules/.ignored/pathe/dist/index.d.mts +0 -36
  236. package/cli/node_modules/.ignored/pathe/dist/index.d.ts +0 -36
  237. package/cli/node_modules/.ignored/pathe/dist/index.mjs +0 -1
  238. package/cli/node_modules/.ignored/pathe/dist/shared/pathe.1f0a373c.cjs +0 -238
  239. package/cli/node_modules/.ignored/pathe/dist/shared/pathe.ff20891b.mjs +0 -221
  240. package/cli/node_modules/.ignored/pathe/dist/utils.cjs +0 -58
  241. package/cli/node_modules/.ignored/pathe/dist/utils.d.cts +0 -5
  242. package/cli/node_modules/.ignored/pathe/dist/utils.d.mts +0 -5
  243. package/cli/node_modules/.ignored/pathe/dist/utils.d.ts +0 -5
  244. package/cli/node_modules/.ignored/pathe/dist/utils.mjs +0 -54
  245. package/cli/node_modules/.ignored/pathe/package.json +0 -48
  246. package/cli/node_modules/.ignored/pathe/utils.d.ts +0 -1
  247. package/cli/node_modules/.ignored/scule/LICENSE +0 -21
  248. package/cli/node_modules/.ignored/scule/README.md +0 -149
  249. package/cli/node_modules/.ignored/scule/dist/index.cjs +0 -92
  250. package/cli/node_modules/.ignored/scule/dist/index.d.cts +0 -57
  251. package/cli/node_modules/.ignored/scule/dist/index.d.mts +0 -57
  252. package/cli/node_modules/.ignored/scule/dist/index.d.ts +0 -57
  253. package/cli/node_modules/.ignored/scule/dist/index.mjs +0 -80
  254. package/cli/node_modules/.ignored/scule/package.json +0 -43
  255. package/cli/node_modules/.package-lock.json +0 -33
  256. package/dist/runtime/types/component.d.ts +0 -17
  257. package/dist/runtime/types/component.js +0 -0
@@ -1,3 +1,4 @@
1
+ <!-- eslint-disable vue/block-tag-newline -->
1
2
  <script lang="ts">
2
3
  import { tv } from 'tailwind-variants'
3
4
  import type { DropdownMenuContentProps as RadixDropdownMenuContentProps, DropdownMenuContentEmits as RadixDropdownMenuContentEmits } from 'radix-vue'
@@ -10,6 +11,9 @@ interface DropdownMenuContentProps<T> extends Omit<RadixDropdownMenuContentProps
10
11
  items?: T[] | T[][]
11
12
  portal?: boolean
12
13
  sub?: boolean
14
+ labelKey: string
15
+ checkedIcon?: string
16
+ loadingIcon?: string
13
17
  class?: any
14
18
  ui: typeof _dropdownMenu
15
19
  uiOverride?: any
@@ -20,6 +24,7 @@ interface DropdownMenuContentEmits extends RadixDropdownMenuContentEmits {}
20
24
  type DropdownMenuContentSlots<T extends { slot?: string }> = Omit<DropdownMenuSlots<T>, 'default'> & {
21
25
  default(props?: {}): any
22
26
  }
27
+
23
28
  </script>
24
29
 
25
30
  <script setup lang="ts" generic="T extends DropdownMenuItem">
@@ -28,13 +33,13 @@ import { DropdownMenu } from 'radix-vue/namespaced'
28
33
  import { useForwardPropsEmits } from 'radix-vue'
29
34
  import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
30
35
  import { useAppConfig } from '#imports'
36
+ import { omit, get } from '../utils'
37
+ import { pickLinkProps } from '../utils/link'
31
38
  import ULinkBase from './LinkBase.vue'
32
39
  import ULink from './Link.vue'
33
40
  import UAvatar from './Avatar.vue'
34
41
  import UIcon from './Icon.vue'
35
42
  import UKbd from './Kbd.vue'
36
- import { omit } from '../utils'
37
- import { pickLinkProps } from '../utils/link'
38
43
 
39
44
  const props = defineProps<DropdownMenuContentProps<T>>()
40
45
  const emits = defineEmits<DropdownMenuContentEmits>()
@@ -53,25 +58,30 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
53
58
  <DefineItemTemplate v-slot="{ item, active, index }">
54
59
  <slot :name="item.slot || 'item'" :item="(item as T)" :index="index">
55
60
  <slot :name="item.slot ? `${item.slot}-leading`: 'item-leading'" :item="(item as T)" :active="active" :index="index">
56
- <UAvatar v-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
57
- <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, active })" />
61
+ <UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
62
+ <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
63
+ <UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
58
64
  </slot>
59
65
 
60
- <span v-if="item.label || !!slots[item.slot ? `${item.slot}-label`: 'item-label']" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
66
+ <span v-if="get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label`: 'item-label']" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
61
67
  <slot :name="item.slot ? `${item.slot}-label`: 'item-label'" :item="(item as T)" :active="active" :index="index">
62
- {{ item.label }}
68
+ {{ get(item, props.labelKey as string) }}
63
69
  </slot>
64
70
 
65
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, active })" />
71
+ <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
66
72
  </span>
67
73
 
68
- <span v-if="item.children?.length || item.kbds?.length || !!slots[item.slot ? `${item.slot}-trailing`: 'item-trailing']" :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
74
+ <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
69
75
  <slot :name="item.slot ? `${item.slot}-trailing`: 'item-trailing'" :item="(item as T)" :active="active" :index="index">
70
- <UIcon v-if="item.children?.length" :name="appConfig.ui.icons.chevronRight" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, active })" />
76
+ <UIcon v-if="item.children?.length" :name="appConfig.ui.icons.chevronRight" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
71
77
  <span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
72
78
  <UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
73
79
  </span>
74
80
  </slot>
81
+
82
+ <DropdownMenu.ItemIndicator as-child>
83
+ <UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color })" />
84
+ </DropdownMenu.ItemIndicator>
75
85
  </span>
76
86
  </slot>
77
87
  </DefineItemTemplate>
@@ -89,8 +99,8 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
89
99
  as="button"
90
100
  type="button"
91
101
  :disabled="item.disabled"
92
- :text-value="item.label"
93
- :class="ui.item({ class: uiOverride?.item })"
102
+ :text-value="get(item, props.labelKey as string)"
103
+ :class="ui.item({ class: uiOverride?.item, color: item?.color })"
94
104
  >
95
105
  <ReuseItemTemplate :item="item" :index="index" />
96
106
  </DropdownMenu.SubTrigger>
@@ -106,6 +116,9 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
106
116
  align="start"
107
117
  :align-offset="-4"
108
118
  :side-offset="3"
119
+ :label-key="labelKey"
120
+ :checked-icon="checkedIcon"
121
+ :loading-icon="loadingIcon"
109
122
  v-bind="item.content"
110
123
  >
111
124
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
@@ -113,9 +126,26 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
113
126
  </template>
114
127
  </UDropdownMenuContent>
115
128
  </DropdownMenu.Sub>
116
- <DropdownMenu.Item v-else as-child :disabled="item.disabled" :text-value="item.label" @select="item.select">
129
+ <DropdownMenu.CheckboxItem
130
+ v-else-if="item.type === 'checkbox'"
131
+ :checked="item.checked"
132
+ :disabled="item.disabled"
133
+ :text-value="get(item, props.labelKey as string)"
134
+ :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
135
+ @update:checked="item.onUpdateChecked"
136
+ @select="item.onSelect"
137
+ >
138
+ <ReuseItemTemplate :item="item" :index="index" />
139
+ </DropdownMenu.CheckboxItem>
140
+ <DropdownMenu.Item
141
+ v-else
142
+ as-child
143
+ :disabled="item.disabled"
144
+ :text-value="get(item, props.labelKey as string)"
145
+ @select="item.onSelect"
146
+ >
117
147
  <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom>
118
- <ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], active })">
148
+ <ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color, active })">
119
149
  <ReuseItemTemplate :item="item" :active="active" :index="index" />
120
150
  </ULinkBase>
121
151
  </ULink>
@@ -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/form'
6
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
6
7
  import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
7
8
 
8
9
  const appConfig = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
@@ -29,13 +30,15 @@ export interface FormEmits<T extends object> {
29
30
  export interface FormSlots {
30
31
  default(props?: {}): any
31
32
  }
33
+
34
+ extendDevtoolsMeta({ example: 'FormExample' })
32
35
  </script>
33
36
 
34
37
  <script lang="ts" setup generic="T extends object">
35
38
  import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
36
39
  import { useEventBus } from '@vueuse/core'
37
40
  import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
38
- import { getYupErrors, isYupSchema, getValibotErrors, isValibotSchema, getZodErrors, isZodSchema, getJoiErrors, isJoiSchema, getStandardErrors, isStandardSchema } from '../utils/form'
41
+ import { getYupErrors, isYupSchema, getValibotErrors, isValibotSchema, getZodErrors, isZodSchema, getJoiErrors, isJoiSchema, getStandardErrors, isStandardSchema, getSuperStructErrors, isSuperStructSchema } from '../utils/form'
39
42
  import { FormValidationException } from '../types/form'
40
43
 
41
44
  const props = withDefaults(defineProps<FormProps<T>>(), {
@@ -113,6 +116,8 @@ async function getErrors(): Promise<FormErrorWithId[]> {
113
116
  errs = errs.concat(await getJoiErrors(props.state, props.schema))
114
117
  } else if (isValibotSchema(props.schema)) {
115
118
  errs = errs.concat(await getValibotErrors(props.state, props.schema))
119
+ } else if (isSuperStructSchema(props.schema)) {
120
+ errs = errs.concat(await getSuperStructErrors(props.state, props.schema))
116
121
  } else if (isStandardSchema(props.schema)) {
117
122
  errs = errs.concat(await getStandardErrors(props.state, props.schema))
118
123
  } else {
@@ -3,6 +3,7 @@ import { tv, type VariantProps } 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/form-field'
6
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
6
7
 
7
8
  const appConfig = _appConfig as AppConfig & { ui: { formField: Partial<typeof theme> } }
8
9
 
@@ -33,6 +34,8 @@ export interface FormFieldSlots {
33
34
  error(props: { error?: string | boolean }): any
34
35
  default(props: { error?: string | boolean }): any
35
36
  }
37
+
38
+ extendDevtoolsMeta({ example: 'FormFieldExample', defaultProps: { label: 'Label' } })
36
39
  </script>
37
40
 
38
41
  <script setup lang="ts">
@@ -5,6 +5,7 @@ import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/input'
7
7
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
+ import type { AvatarProps } from '../types'
8
9
  import type { PartialString } from '../types/utils'
9
10
 
10
11
  const appConfig = _appConfig as AppConfig & { ui: { input: Partial<typeof theme> } }
@@ -51,8 +52,9 @@ import { ref, computed, onMounted } from 'vue'
51
52
  import { useButtonGroup } from '../composables/useButtonGroup'
52
53
  import { useComponentIcons } from '../composables/useComponentIcons'
53
54
  import { useFormField } from '../composables/useFormField'
54
- import UIcon from './Icon.vue'
55
55
  import { looseToNumber } from '../utils'
56
+ import UIcon from './Icon.vue'
57
+ import UAvatar from './Avatar.vue'
56
58
 
57
59
  defineOptions({ inheritAttrs: false })
58
60
 
@@ -79,7 +81,7 @@ const ui = computed(() => input({
79
81
  size: inputSize?.value,
80
82
  loading: props.loading,
81
83
  highlight: highlight.value,
82
- leading: isLeading.value || !!slots.leading,
84
+ leading: isLeading.value || !!props.avatar || !!slots.leading,
83
85
  trailing: isTrailing.value || !!slots.trailing,
84
86
  buttonGroup: orientation.value
85
87
  }))
@@ -165,9 +167,10 @@ onMounted(() => {
165
167
 
166
168
  <slot />
167
169
 
168
- <span v-if="isLeading || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
170
+ <span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
169
171
  <slot name="leading">
170
- <UIcon v-if="leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
172
+ <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
173
+ <UAvatar v-else-if="!!avatar" :size="((props.ui?.leadingAvatarSize || ui.leadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.leadingAvatar({ class: props.ui?.leadingAvatar })" />
171
174
  </slot>
172
175
  </span>
173
176
 
@@ -1,19 +1,20 @@
1
1
  <script lang="ts">
2
2
  import type { InputHTMLAttributes } from 'vue'
3
3
  import { tv, type VariantProps } from 'tailwind-variants'
4
- import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxItemProps, ComboboxArrowProps } from 'radix-vue'
4
+ import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps } from 'radix-vue'
5
5
  import type { AppConfig } from '@nuxt/schema'
6
6
  import _appConfig from '#build/app.config'
7
7
  import theme from '#build/ui/input-menu'
8
8
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
9
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
9
10
  import type { AvatarProps, ChipProps, InputProps } from '../types'
10
- import type { AcceptableValue, ArrayOrWrapped, PartialString } from '../types/utils'
11
+ import type { AcceptableValue, ArrayOrWrapped, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
11
12
 
12
13
  const appConfig = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
13
14
 
14
15
  const inputMenu = tv({ extend: tv(theme), ...(appConfig.ui?.inputMenu || {}) })
15
16
 
16
- export interface InputMenuItem extends Pick<ComboboxItemProps, 'disabled'> {
17
+ export interface InputMenuItem {
17
18
  label?: string
18
19
  icon?: string
19
20
  avatar?: AvatarProps
@@ -23,12 +24,13 @@ export interface InputMenuItem extends Pick<ComboboxItemProps, 'disabled'> {
23
24
  * @defaultValue 'item'
24
25
  */
25
26
  type?: 'label' | 'separator' | 'item'
26
- select?(e?: Event): void
27
+ disabled?: boolean
28
+ onSelect?(e?: Event): void
27
29
  }
28
30
 
29
31
  type InputMenuVariants = VariantProps<typeof inputMenu>
30
32
 
31
- export interface InputMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValue' | 'defaultValue' | 'selectedValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'multiple' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
33
+ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue> = MaybeArrayOfArray<InputMenuItem | 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
34
  /**
33
35
  * The element or component this component should render as.
34
36
  * @defaultValue 'div'
@@ -85,19 +87,28 @@ export interface InputMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValu
85
87
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
86
88
  * @defaultValue undefined
87
89
  */
88
- valueKey?: keyof T
89
- items?: T[] | T[][]
90
+ valueKey?: V
91
+ /**
92
+ * When `items` is an array of objects, select the field to use as the label.
93
+ * @defaultValue 'label'
94
+ */
95
+ labelKey?: keyof T
96
+ items?: I
90
97
  /** Highlight the ring color like a focus state. */
91
98
  highlight?: boolean
92
99
  class?: any
93
100
  ui?: PartialString<typeof inputMenu.slots>
101
+ /** The controlled value of the Combobox. Can be binded-with with `v-model`. */
102
+ modelValue?: SelectModelValue<T, V, M>
103
+ /** Whether multiple options can be selected or not. */
104
+ multiple?: M
94
105
  }
95
106
 
96
- export type InputMenuEmits<T> = ComboboxRootEmits<T> & {
107
+ export type InputMenuEmits<T, V, M extends boolean> = Omit<ComboboxRootEmits<T>, 'update:modelValue'> & {
97
108
  change: [payload: Event]
98
109
  blur: [payload: FocusEvent]
99
110
  focus: [payload: FocusEvent]
100
- }
111
+ } & SelectModelValueEmits<T, V, M>
101
112
 
102
113
  type SlotProps<T> = (props: { item: T, index: number }) => any
103
114
 
@@ -112,31 +123,35 @@ export interface InputMenuSlots<T> {
112
123
  'tags-item-text': SlotProps<T>
113
124
  'tags-item-delete': SlotProps<T>
114
125
  }
126
+
127
+ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
115
128
  </script>
116
129
 
117
- <script setup lang="ts" generic="T extends InputMenuItem | AcceptableValue">
130
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue> = MaybeArrayOfArray<InputMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
118
131
  import { computed, ref, toRef, onMounted } from 'vue'
119
- import { ComboboxRoot, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits } from 'radix-vue'
132
+ import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits } from 'radix-vue'
120
133
  import { defu } from 'defu'
134
+ import * as isEqual from 'fast-deep-equal'
121
135
  import { reactivePick } from '@vueuse/core'
122
136
  import { useAppConfig } from '#imports'
123
137
  import { useButtonGroup } from '../composables/useButtonGroup'
124
138
  import { useComponentIcons } from '../composables/useComponentIcons'
125
139
  import { useFormField } from '../composables/useFormField'
140
+ import { get, escapeRegExp } from '../utils'
126
141
  import UIcon from './Icon.vue'
127
142
  import UAvatar from './Avatar.vue'
128
143
  import UChip from './Chip.vue'
129
- import { get } from '../utils'
130
144
 
131
145
  defineOptions({ inheritAttrs: false })
132
146
 
133
- const props = withDefaults(defineProps<InputMenuProps<T>>(), {
147
+ const props = withDefaults(defineProps<InputMenuProps<T, I, V, M>>(), {
134
148
  type: 'text',
135
149
  autofocusDelay: 0,
136
150
  portal: true,
137
- filter: () => ['label']
151
+ filter: () => ['label'],
152
+ labelKey: 'label' as keyof T
138
153
  })
139
- const emits = defineEmits<InputMenuEmits<T>>()
154
+ const emits = defineEmits<InputMenuEmits<T, V, M>>()
140
155
  const slots = defineSlots<InputMenuSlots<T>>()
141
156
 
142
157
  const searchTerm = defineModel<string>('searchTerm', { default: '' })
@@ -144,6 +159,8 @@ const searchTerm = defineModel<string>('searchTerm', { default: '' })
144
159
  const appConfig = useAppConfig()
145
160
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits)
146
161
  const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
162
+ const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
163
+
147
164
  const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
148
165
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
149
166
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
@@ -156,18 +173,16 @@ const ui = computed(() => inputMenu({
156
173
  size: inputSize?.value,
157
174
  loading: props.loading,
158
175
  highlight: highlight.value,
159
- leading: isLeading.value || !!slots.leading,
176
+ leading: isLeading.value || !!props.avatar || !!slots.leading,
160
177
  trailing: isTrailing.value || !!slots.trailing,
161
178
  multiple: props.multiple,
162
179
  buttonGroup: orientation.value
163
180
  }))
164
181
 
165
- function displayValue(val: AcceptableValue) {
166
- if (typeof val === 'object') {
167
- return val.label
168
- }
182
+ function displayValue(value: AcceptableValue): string {
183
+ 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))
169
184
 
170
- return val && String(val)
185
+ return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
171
186
  }
172
187
 
173
188
  function filterFunction(items: ArrayOrWrapped<AcceptableValue>, searchTerm: string): ArrayOrWrapped<AcceptableValue> {
@@ -175,22 +190,25 @@ function filterFunction(items: ArrayOrWrapped<AcceptableValue>, searchTerm: stri
175
190
  return items
176
191
  }
177
192
 
178
- const fields = Array.isArray(props.filter) ? props.filter : ['label']
193
+ const fields = Array.isArray(props.filter) ? props.filter : [props.labelKey]
194
+ const escapedSearchTerm = escapeRegExp(searchTerm)
179
195
 
180
196
  return items.filter((item) => {
181
197
  if (typeof item !== 'object') {
182
- return String(item).search(new RegExp(searchTerm, 'i')) !== -1
198
+ return String(item).search(new RegExp(escapedSearchTerm, 'i')) !== -1
183
199
  }
184
200
 
185
201
  return fields.some((field) => {
186
- const child = get(item, field)
202
+ const child = get(item, field as string)
187
203
 
188
- return child !== null && child !== undefined && String(child).search(new RegExp(searchTerm, 'i')) !== -1
204
+ return child !== null && child !== undefined && String(child).search(new RegExp(escapedSearchTerm, 'i')) !== -1
189
205
  })
190
206
  }) as ArrayOrWrapped<T>
191
207
  }
192
208
 
193
209
  const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as InputMenuItem[][] : [])
210
+ // eslint-disable-next-line vue/no-dupe-keys
211
+ const items = computed(() => groups.value.flatMap(group => group) as T[])
194
212
 
195
213
  const inputRef = ref<InstanceType<typeof ComboboxInput> | null>(null)
196
214
 
@@ -219,6 +237,10 @@ function onBlur(event: FocusEvent) {
219
237
  emitFormBlur()
220
238
  }
221
239
 
240
+ function onFocus(event: FocusEvent) {
241
+ emits('focus', event)
242
+ }
243
+
222
244
  function onUpdateOpen(value: boolean) {
223
245
  if (!value) {
224
246
  const event = new FocusEvent('blur')
@@ -260,11 +282,12 @@ defineExpose({
260
282
  delimiter=""
261
283
  as-child
262
284
  @blur="onBlur"
285
+ @focus="onFocus"
263
286
  >
264
287
  <TagsInputItem v-for="(item, index) in tags" :key="index" :value="(item as string)" :class="ui.tagsItem({ class: props.ui?.tagsItem })">
265
288
  <TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
266
289
  <slot name="tags-item-text" :item="(item as T)" :index="index">
267
- {{ typeof item === 'object' ? item.label : item }}
290
+ {{ displayValue(item as T) }}
268
291
  </slot>
269
292
  </TagsInputItemText>
270
293
 
@@ -296,11 +319,13 @@ defineExpose({
296
319
  :required="required"
297
320
  :class="ui.base({ class: props.ui?.base })"
298
321
  @blur="onBlur"
322
+ @focus="onFocus"
299
323
  />
300
324
 
301
- <span v-if="isLeading || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
325
+ <span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
302
326
  <slot name="leading" :model-value="(modelValue as T)" :open="open" :ui="ui">
303
- <UIcon v-if="leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
327
+ <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
328
+ <UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
304
329
  </slot>
305
330
  </span>
306
331
 
@@ -323,7 +348,7 @@ defineExpose({
323
348
  <ComboboxGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
324
349
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
325
350
  <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
326
- {{ item.label }}
351
+ {{ get(item, props.labelKey as string) }}
327
352
  </ComboboxLabel>
328
353
 
329
354
  <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
@@ -332,13 +357,13 @@ defineExpose({
332
357
  v-else
333
358
  :class="ui.item({ class: props.ui?.item })"
334
359
  :disabled="item.disabled"
335
- :value="valueKey && typeof item === 'object' ? (item[valueKey as keyof InputMenuItem]) as AcceptableValue : item"
336
- @select="item.select"
360
+ :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
361
+ @select="item.onSelect"
337
362
  >
338
363
  <slot name="item" :item="(item as T)" :index="index">
339
364
  <slot name="item-leading" :item="(item as T)" :index="index">
340
- <UAvatar v-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
341
- <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
365
+ <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
366
+ <UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
342
367
  <UChip
343
368
  v-else-if="item.chip"
344
369
  :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
@@ -351,7 +376,7 @@ defineExpose({
351
376
 
352
377
  <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
353
378
  <slot name="item-label" :item="(item as T)" :index="index">
354
- {{ displayValue(item as T) }}
379
+ {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
355
380
  </slot>
356
381
  </span>
357
382
 
@@ -367,6 +392,8 @@ defineExpose({
367
392
  </template>
368
393
  </ComboboxGroup>
369
394
  </ComboboxViewport>
395
+
396
+ <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
370
397
  </ComboboxContent>
371
398
  </ComboboxPortal>
372
399
  </ComboboxRoot>
@@ -4,6 +4,7 @@ import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/ui/kbd'
6
6
  import type { KbdKey } from '../composables/useKbd'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
 
8
9
  const appConfig = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
9
10
 
@@ -26,6 +27,7 @@ export interface KbdProps {
26
27
  export interface KbdSlots {
27
28
  default(props?: {}): any
28
29
  }
30
+ extendDevtoolsMeta({ defaultProps: { value: 'K' } })
29
31
  </script>
30
32
 
31
33
  <script setup lang="ts">
@@ -3,8 +3,55 @@ import type { ButtonHTMLAttributes } from 'vue'
3
3
  import { tv } from 'tailwind-variants'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
+ import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
6
7
  import theme from '#build/ui/link'
7
- import type { NuxtLinkProps } from '#app'
8
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
9
+
10
+ interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
11
+ /**
12
+ * Route Location the link should navigate to when clicked on.
13
+ */
14
+ to?: RouteLocationRaw // need to manually type to avoid breaking typedPages
15
+ /**
16
+ * An alias for `to`. If used with `to`, `href` will be ignored
17
+ */
18
+ href?: NuxtLinkProps['to']
19
+ /**
20
+ * Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases
21
+ */
22
+ external?: boolean
23
+ /**
24
+ * Where to display the linked URL, as the name for a browsing context.
25
+ */
26
+ target?: '_blank' | '_parent' | '_self' | '_top' | (string & {}) | null
27
+ /**
28
+ * A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links.
29
+ */
30
+ rel?: 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | (string & {}) | null
31
+ /**
32
+ * If set to true, no rel attribute will be added to the link
33
+ */
34
+ noRel?: boolean
35
+ /**
36
+ * A class to apply to links that have been prefetched.
37
+ */
38
+ prefetchedClass?: string
39
+ /**
40
+ * When enabled will prefetch middleware, layouts and payloads of links in the viewport.
41
+ */
42
+ prefetch?: boolean
43
+ /**
44
+ * Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
45
+ */
46
+ prefetchOn?: 'visibility' | 'interaction' | Partial<{
47
+ visibility: boolean
48
+ interaction: boolean
49
+ }>
50
+ /**
51
+ * Escape hatch to disable `prefetch` attribute.
52
+ */
53
+ noPrefetch?: boolean
54
+ }
8
55
 
9
56
  const appConfig = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
10
57
 
@@ -41,6 +88,8 @@ export interface LinkProps extends NuxtLinkProps {
41
88
  export interface LinkSlots {
42
89
  default(props: { active: boolean }): any
43
90
  }
91
+
92
+ extendDevtoolsMeta({ example: 'LinkExample' })
44
93
  </script>
45
94
 
46
95
  <script setup lang="ts">
@@ -3,7 +3,7 @@ export interface LinkBaseProps {
3
3
  as?: string
4
4
  type?: string
5
5
  disabled?: boolean
6
- onClick?: (e: MouseEvent) => void | Promise<void>
6
+ onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
7
7
  href?: string
8
8
  navigate?: (e: MouseEvent) => void
9
9
  rel?: string
@@ -28,7 +28,9 @@ function onClickWrapper(e: MouseEvent) {
28
28
  }
29
29
 
30
30
  if (props.onClick) {
31
- props.onClick(e)
31
+ for (const onClick of Array.isArray(props.onClick) ? props.onClick : [props.onClick]) {
32
+ onClick(e)
33
+ }
32
34
  }
33
35
 
34
36
  if (props.href && props.navigate && !props.isExternal) {
@@ -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/modal'
7
+ import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
  import type { ButtonProps } from '../types'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { modal: Partial<typeof theme> } }
@@ -67,6 +68,8 @@ export interface ModalSlots {
67
68
  body(props?: {}): any
68
69
  footer(props?: {}): any
69
70
  }
71
+
72
+ extendDevtoolsMeta({ example: 'ModalExample' })
70
73
  </script>
71
74
 
72
75
  <script setup lang="ts">