@nuxt/ui 3.0.0-alpha.9 → 3.0.0-beta.2

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 (289) hide show
  1. package/.nuxt/ui/accordion.ts +2 -2
  2. package/.nuxt/ui/alert.ts +122 -95
  3. package/.nuxt/ui/avatar-group.ts +14 -2
  4. package/.nuxt/ui/avatar.ts +16 -4
  5. package/.nuxt/ui/badge.ts +139 -93
  6. package/.nuxt/ui/breadcrumb.ts +5 -5
  7. package/.nuxt/ui/button-group.ts +13 -0
  8. package/.nuxt/ui/button.ts +167 -136
  9. package/.nuxt/ui/calendar.ts +103 -0
  10. package/.nuxt/ui/card.ts +27 -1
  11. package/.nuxt/ui/carousel.ts +7 -5
  12. package/.nuxt/ui/checkbox.ts +45 -27
  13. package/.nuxt/ui/chip.ts +44 -15
  14. package/.nuxt/ui/color-picker.ts +47 -0
  15. package/.nuxt/ui/command-palette.ts +28 -18
  16. package/.nuxt/ui/container.ts +1 -1
  17. package/.nuxt/ui/context-menu.ts +64 -46
  18. package/.nuxt/ui/drawer.ts +83 -15
  19. package/.nuxt/ui/dropdown-menu.ts +65 -47
  20. package/.nuxt/ui/form-field.ts +15 -7
  21. package/.nuxt/ui/index.ts +5 -1
  22. package/.nuxt/ui/input-menu.ts +150 -116
  23. package/.nuxt/ui/input-number.ts +102 -71
  24. package/.nuxt/ui/input.ts +111 -76
  25. package/.nuxt/ui/kbd.ts +18 -6
  26. package/.nuxt/ui/link.ts +3 -3
  27. package/.nuxt/ui/modal.ts +8 -7
  28. package/.nuxt/ui/navigation-menu.ts +244 -131
  29. package/.nuxt/ui/pin-input.ts +77 -51
  30. package/.nuxt/ui/popover.ts +2 -2
  31. package/.nuxt/ui/progress.ts +111 -72
  32. package/.nuxt/ui/radio-group.ts +45 -22
  33. package/.nuxt/ui/select-menu.ts +122 -86
  34. package/.nuxt/ui/select.ts +120 -84
  35. package/.nuxt/ui/separator.ts +60 -31
  36. package/.nuxt/ui/skeleton.ts +1 -1
  37. package/.nuxt/ui/slideover.ts +17 -9
  38. package/.nuxt/ui/slider.ts +61 -38
  39. package/.nuxt/ui/stepper.ts +202 -0
  40. package/.nuxt/ui/switch.ts +40 -22
  41. package/.nuxt/ui/table.ts +48 -31
  42. package/.nuxt/ui/tabs.ts +100 -72
  43. package/.nuxt/ui/textarea.ts +111 -76
  44. package/.nuxt/ui/toast.ts +53 -33
  45. package/.nuxt/ui/toaster.ts +31 -15
  46. package/.nuxt/ui/tooltip.ts +2 -2
  47. package/.nuxt/ui/tree.ts +154 -0
  48. package/.nuxt/ui.css +92 -0
  49. package/README.md +19 -8
  50. package/cli/commands/make/component.mjs +12 -0
  51. package/cli/package.json +2 -2
  52. package/cli/templates.mjs +27 -22
  53. package/dist/module.cjs +9 -171
  54. package/dist/module.d.cts +5 -15
  55. package/dist/module.d.mts +5 -15
  56. package/dist/module.d.ts +5 -15
  57. package/dist/module.json +2 -2
  58. package/dist/module.mjs +12 -168
  59. package/dist/runtime/components/Accordion.vue +8 -39
  60. package/dist/runtime/components/Alert.vue +22 -21
  61. package/dist/runtime/components/App.vue +9 -15
  62. package/dist/runtime/components/Avatar.vue +33 -21
  63. package/dist/runtime/components/AvatarGroup.vue +5 -7
  64. package/dist/runtime/components/Badge.vue +10 -8
  65. package/dist/runtime/components/Breadcrumb.vue +5 -31
  66. package/dist/runtime/components/Button.vue +5 -8
  67. package/dist/runtime/components/ButtonGroup.vue +5 -7
  68. package/dist/runtime/components/Calendar.vue +194 -0
  69. package/dist/runtime/components/Card.vue +10 -9
  70. package/dist/runtime/components/Carousel.vue +15 -10
  71. package/dist/runtime/components/Checkbox.vue +32 -38
  72. package/dist/runtime/components/Chip.vue +6 -8
  73. package/dist/runtime/components/Collapsible.vue +10 -11
  74. package/dist/runtime/components/ColorPicker.vue +297 -0
  75. package/dist/runtime/components/CommandPalette.vue +111 -97
  76. package/dist/runtime/components/Container.vue +4 -7
  77. package/dist/runtime/components/ContextMenu.vue +16 -69
  78. package/dist/runtime/components/ContextMenuContent.vue +12 -10
  79. package/dist/runtime/components/Drawer.vue +23 -12
  80. package/dist/runtime/components/DropdownMenu.vue +18 -59
  81. package/dist/runtime/components/DropdownMenuContent.vue +12 -10
  82. package/dist/runtime/components/Form.vue +65 -34
  83. package/dist/runtime/components/FormField.vue +22 -13
  84. package/dist/runtime/components/Icon.vue +1 -1
  85. package/dist/runtime/components/Input.vue +15 -7
  86. package/dist/runtime/components/InputMenu.vue +95 -104
  87. package/dist/runtime/components/InputNumber.vue +14 -9
  88. package/dist/runtime/components/Kbd.vue +5 -6
  89. package/dist/runtime/components/Link.vue +5 -8
  90. package/dist/runtime/components/LinkBase.vue +1 -1
  91. package/dist/runtime/components/Modal.vue +51 -38
  92. package/dist/runtime/components/NavigationMenu.vue +129 -114
  93. package/dist/runtime/components/OverlayProvider.vue +29 -0
  94. package/dist/runtime/components/Pagination.vue +6 -9
  95. package/dist/runtime/components/PinInput.vue +10 -11
  96. package/dist/runtime/components/Popover.vue +16 -18
  97. package/dist/runtime/components/Progress.vue +28 -12
  98. package/dist/runtime/components/RadioGroup.vue +9 -12
  99. package/dist/runtime/components/Select.vue +60 -34
  100. package/dist/runtime/components/SelectMenu.vue +160 -165
  101. package/dist/runtime/components/Separator.vue +6 -5
  102. package/dist/runtime/components/Skeleton.vue +4 -7
  103. package/dist/runtime/components/Slideover.vue +51 -37
  104. package/dist/runtime/components/Slider.vue +8 -7
  105. package/dist/runtime/components/Stepper.vue +170 -0
  106. package/dist/runtime/components/Switch.vue +19 -23
  107. package/dist/runtime/components/Table.vue +146 -31
  108. package/dist/runtime/components/Tabs.vue +12 -31
  109. package/dist/runtime/components/Textarea.vue +17 -8
  110. package/dist/runtime/components/Toast.vue +36 -25
  111. package/dist/runtime/components/Toaster.vue +10 -11
  112. package/dist/runtime/components/Tooltip.vue +9 -12
  113. package/dist/runtime/components/Tree.vue +196 -0
  114. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  115. package/dist/runtime/composables/defineShortcuts.js +2 -2
  116. package/dist/runtime/composables/useFormField.d.ts +7 -3
  117. package/dist/runtime/composables/useFormField.js +18 -8
  118. package/dist/runtime/composables/useLocale.js +1 -1
  119. package/dist/runtime/composables/useOverlay.d.ts +30 -0
  120. package/dist/runtime/composables/useOverlay.js +71 -0
  121. package/dist/runtime/composables/useToast.d.ts +4 -3
  122. package/dist/runtime/composables/useToast.js +20 -6
  123. package/dist/runtime/index.css +1 -1
  124. package/dist/runtime/keyframes.css +1 -1
  125. package/dist/runtime/locale/ar.js +9 -1
  126. package/dist/runtime/locale/az.js +54 -0
  127. package/dist/runtime/locale/bn.js +54 -0
  128. package/dist/runtime/locale/cs.js +9 -1
  129. package/dist/runtime/locale/da.d.ts +2 -0
  130. package/dist/runtime/locale/da.js +54 -0
  131. package/dist/runtime/locale/de.js +11 -3
  132. package/dist/runtime/locale/el.d.ts +2 -0
  133. package/dist/runtime/locale/el.js +54 -0
  134. package/dist/runtime/locale/en.js +9 -1
  135. package/dist/runtime/locale/es.js +9 -1
  136. package/dist/runtime/locale/et.d.ts +2 -0
  137. package/dist/runtime/locale/et.js +54 -0
  138. package/dist/runtime/locale/fa_ir.js +9 -1
  139. package/dist/runtime/locale/fi.d.ts +2 -0
  140. package/dist/runtime/locale/fi.js +54 -0
  141. package/dist/runtime/locale/fr.js +9 -1
  142. package/dist/runtime/locale/he.d.ts +2 -0
  143. package/dist/runtime/locale/he.js +53 -0
  144. package/dist/runtime/locale/hi.d.ts +2 -0
  145. package/dist/runtime/locale/hi.js +54 -0
  146. package/dist/runtime/locale/hu.d.ts +2 -0
  147. package/dist/runtime/locale/hu.js +54 -0
  148. package/dist/runtime/locale/id.d.ts +2 -0
  149. package/dist/runtime/locale/id.js +54 -0
  150. package/dist/runtime/locale/index.d.ts +25 -3
  151. package/dist/runtime/locale/index.js +25 -3
  152. package/dist/runtime/locale/it.js +9 -1
  153. package/dist/runtime/locale/ja.d.ts +2 -0
  154. package/dist/runtime/locale/ja.js +54 -0
  155. package/dist/runtime/locale/km.d.ts +2 -0
  156. package/dist/runtime/locale/km.js +54 -0
  157. package/dist/runtime/locale/ko.d.ts +2 -0
  158. package/dist/runtime/locale/ko.js +54 -0
  159. package/dist/runtime/locale/nb_no.d.ts +2 -0
  160. package/dist/runtime/locale/nb_no.js +54 -0
  161. package/dist/runtime/locale/nl.d.ts +2 -0
  162. package/dist/runtime/locale/nl.js +54 -0
  163. package/dist/runtime/locale/pl.js +9 -1
  164. package/dist/runtime/locale/pt.d.ts +2 -0
  165. package/dist/runtime/locale/pt.js +54 -0
  166. package/dist/runtime/locale/pt_br.d.ts +2 -0
  167. package/dist/runtime/locale/pt_br.js +54 -0
  168. package/dist/runtime/locale/ru.js +9 -1
  169. package/dist/runtime/locale/sk.d.ts +2 -0
  170. package/dist/runtime/locale/sk.js +54 -0
  171. package/dist/runtime/locale/sv.d.ts +2 -0
  172. package/dist/runtime/locale/sv.js +54 -0
  173. package/dist/runtime/locale/th.d.ts +2 -0
  174. package/dist/runtime/locale/th.js +54 -0
  175. package/dist/runtime/locale/tr.d.ts +2 -0
  176. package/dist/runtime/locale/tr.js +54 -0
  177. package/dist/runtime/locale/uk.d.ts +2 -0
  178. package/dist/runtime/locale/uk.js +54 -0
  179. package/dist/runtime/locale/vi.d.ts +2 -0
  180. package/dist/runtime/locale/vi.js +54 -0
  181. package/dist/runtime/locale/zh_cn.d.ts +2 -0
  182. package/dist/runtime/locale/{zh_hans.js → zh_cn.js} +10 -2
  183. package/dist/runtime/locale/zh_tw.d.ts +2 -0
  184. package/dist/runtime/locale/{zh_hant.js → zh_tw.js} +16 -8
  185. package/dist/runtime/plugins/colors.js +8 -5
  186. package/dist/runtime/types/form.d.ts +24 -15
  187. package/dist/runtime/types/form.js +2 -2
  188. package/dist/runtime/types/index.d.ts +5 -0
  189. package/dist/runtime/types/index.js +5 -0
  190. package/dist/runtime/types/locale.d.ts +8 -0
  191. package/dist/runtime/types/utils.d.ts +7 -3
  192. package/dist/runtime/utils/form.d.ts +4 -4
  193. package/dist/runtime/utils/form.js +6 -8
  194. package/dist/runtime/utils/index.d.ts +1 -1
  195. package/dist/runtime/utils/index.js +15 -2
  196. package/dist/runtime/utils/tv.d.ts +1 -0
  197. package/dist/runtime/utils/tv.js +4 -0
  198. package/dist/runtime/vue/components/Icon.vue +2 -2
  199. package/dist/runtime/vue/components/Link.vue +87 -23
  200. package/dist/runtime/vue/composables/useAppConfig.d.ts +1 -0
  201. package/dist/runtime/vue/composables/useAppConfig.js +2 -0
  202. package/dist/runtime/vue/plugins/head.d.ts +1 -1
  203. package/dist/runtime/vue/plugins/head.js +3 -3
  204. package/dist/runtime/vue/stubs.d.ts +19 -0
  205. package/dist/runtime/vue/stubs.js +37 -0
  206. package/dist/shared/{ui.d52SSCwA.mjs → ui.DSPu6Y8j.mjs} +905 -401
  207. package/dist/shared/{ui.BPnAe4QS.cjs → ui.DfK2RX6G.cjs} +908 -401
  208. package/dist/unplugin.cjs +62 -26
  209. package/dist/unplugin.d.cts +13 -1
  210. package/dist/unplugin.d.mts +13 -1
  211. package/dist/unplugin.d.ts +13 -1
  212. package/dist/unplugin.mjs +61 -25
  213. package/dist/vite.cjs +3 -2
  214. package/dist/vite.d.cts +2 -0
  215. package/dist/vite.d.mts +2 -0
  216. package/dist/vite.d.ts +2 -0
  217. package/dist/vite.mjs +3 -2
  218. package/package.json +103 -67
  219. package/dist/chunks/component-meta.cjs +0 -77249
  220. package/dist/chunks/component-meta.mjs +0 -77247
  221. package/dist/client/devtools/200.html +0 -1
  222. package/dist/client/devtools/404.html +0 -1
  223. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKK58UfivUw4aw-SK92LTmKP0.woff2 +0 -0
  224. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKy58UfivUw-9uYm8d48E4.woff2 +0 -0
  225. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2 +0 -0
  226. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu6-K6z9mXgjU0-EkYdMs3MAX.woff2 +0 -0
  227. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-7DW3w-R7n06NbhGy.woff +0 -0
  228. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDG3w-leGNfkTmsj.woff +0 -0
  229. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDW3w-ciElMF03ku.woff +0 -0
  230. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JCm3w-sB722Uoa0f.woff +0 -0
  231. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JDW3w-PBDI1JDjwV.woff +0 -0
  232. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8gCm3w-0q1hqVn09O.woff +0 -0
  233. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff +0 -0
  234. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9uCm3w-5TKCIs6EEw.woff +0 -0
  235. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat_XDW3w-r2swRDGfn2.woff +0 -0
  236. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAC5thTQ-ldB60l5U8r.woff +0 -0
  237. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpthTQ-wbFKGFDrgo.woff +0 -0
  238. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpxhTQ-LLUBv5jskj.woff +0 -0
  239. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTQ-F71RdTRbNg.woff +0 -0
  240. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwA_JxhTQ-6nh65gZkc0.woff +0 -0
  241. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTQ-aMoWEJLmTt.woff +0 -0
  242. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTQ-WMBvmLOgKm.woff +0 -0
  243. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAop1hTQ-utGC2hnWq2.woff +0 -0
  244. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTQ-YpyTieVa5B.woff +0 -0
  245. package/dist/client/devtools/_nuxt/BDC8ywlR.js +0 -1
  246. package/dist/client/devtools/_nuxt/BT004Uxp.js +0 -53
  247. package/dist/client/devtools/_nuxt/C1H2Soz3.js +0 -1
  248. package/dist/client/devtools/_nuxt/builds/latest.json +0 -1
  249. package/dist/client/devtools/_nuxt/builds/meta/f98c13ea-d751-4b37-8ce3-94e99708745f.json +0 -1
  250. package/dist/client/devtools/_nuxt/entry.Bx6WJjrx.css +0 -1
  251. package/dist/client/devtools/_nuxt/error-404.Cq4qshcf.css +0 -1
  252. package/dist/client/devtools/_nuxt/error-500.ax1aM34m.css +0 -1
  253. package/dist/client/devtools/favicon.svg +0 -1
  254. package/dist/client/devtools/index.html +0 -1
  255. package/dist/devtools/runtime/DevtoolsRenderer.vue +0 -53
  256. package/dist/devtools/runtime/examples/AvatarGroupExample.vue +0 -7
  257. package/dist/devtools/runtime/examples/ButtonGroupExample.vue +0 -8
  258. package/dist/devtools/runtime/examples/CardExample.vue +0 -13
  259. package/dist/devtools/runtime/examples/CarouselExample.vue +0 -13
  260. package/dist/devtools/runtime/examples/ChipExample.vue +0 -5
  261. package/dist/devtools/runtime/examples/CollapsibleExample.vue +0 -8
  262. package/dist/devtools/runtime/examples/CommandPaletteExample.vue +0 -29
  263. package/dist/devtools/runtime/examples/ContainerExample.vue +0 -5
  264. package/dist/devtools/runtime/examples/ContextMenuExample.vue +0 -5
  265. package/dist/devtools/runtime/examples/DrawerExample.vue +0 -8
  266. package/dist/devtools/runtime/examples/DropdownMenuExample.vue +0 -5
  267. package/dist/devtools/runtime/examples/FormExample.vue +0 -30
  268. package/dist/devtools/runtime/examples/FormFieldExample.vue +0 -5
  269. package/dist/devtools/runtime/examples/LinkExample.vue +0 -5
  270. package/dist/devtools/runtime/examples/ModalExample.vue +0 -8
  271. package/dist/devtools/runtime/examples/PopoverExample.vue +0 -8
  272. package/dist/devtools/runtime/examples/SkeletonExample.vue +0 -3
  273. package/dist/devtools/runtime/examples/SlideoverExample.vue +0 -8
  274. package/dist/devtools/runtime/examples/ToasterExample.vue +0 -11
  275. package/dist/devtools/runtime/examples/TooltipExample.vue +0 -5
  276. package/dist/runtime/components/ModalProvider.vue +0 -12
  277. package/dist/runtime/components/SlideoverProvider.vue +0 -12
  278. package/dist/runtime/composables/extendDevtoolsMeta.d.ts +0 -7
  279. package/dist/runtime/composables/extendDevtoolsMeta.js +0 -2
  280. package/dist/runtime/composables/useModal.d.ts +0 -17
  281. package/dist/runtime/composables/useModal.js +0 -46
  282. package/dist/runtime/composables/useSlideover.d.ts +0 -17
  283. package/dist/runtime/composables/useSlideover.js +0 -46
  284. package/dist/runtime/plugins/modal.d.ts +0 -2
  285. package/dist/runtime/plugins/modal.js +0 -10
  286. package/dist/runtime/plugins/slideover.d.ts +0 -2
  287. package/dist/runtime/plugins/slideover.js +0 -10
  288. /package/dist/runtime/locale/{zh_hans.d.ts → az.d.ts} +0 -0
  289. /package/dist/runtime/locale/{zh_hant.d.ts → bn.d.ts} +0 -0
@@ -1,20 +1,26 @@
1
1
  <script lang="ts">
2
2
  import type { InputHTMLAttributes } from 'vue'
3
- import { tv, type VariantProps } from 'tailwind-variants'
3
+ import type { VariantProps } from 'tailwind-variants'
4
4
  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 { tv } from '../utils/tv'
8
9
  import type { AvatarProps } from '../types'
9
10
  import type { PartialString } from '../types/utils'
10
11
 
11
- const appConfig = _appConfig as AppConfig & { ui: { input: Partial<typeof theme> } }
12
+ const appConfigInput = _appConfig as AppConfig & { ui: { input: Partial<typeof theme> } }
12
13
 
13
- const input = tv({ extend: tv(theme), ...(appConfig.ui?.input || {}) })
14
+ const input = tv({ extend: tv(theme), ...(appConfigInput.ui?.input || {}) })
14
15
 
15
16
  type InputVariants = VariantProps<typeof input>
16
17
 
17
18
  export interface InputProps extends UseComponentIconsProps {
19
+ /**
20
+ * The element or component this component should render as.
21
+ * @defaultValue 'div'
22
+ */
23
+ as?: any
18
24
  id?: string
19
25
  name?: string
20
26
  type?: InputHTMLAttributes['type']
@@ -49,6 +55,7 @@ export interface InputSlots {
49
55
 
50
56
  <script setup lang="ts">
51
57
  import { ref, computed, onMounted } from 'vue'
58
+ import { Primitive } from 'reka-ui'
52
59
  import { useButtonGroup } from '../composables/useButtonGroup'
53
60
  import { useComponentIcons } from '../composables/useComponentIcons'
54
61
  import { useFormField } from '../composables/useFormField'
@@ -68,7 +75,7 @@ const slots = defineSlots<InputSlots>()
68
75
 
69
76
  const [modelValue, modelModifiers] = defineModel<string | number>()
70
77
 
71
- const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
78
+ const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField<InputProps>(props, { deferInputValidation: true })
72
79
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
73
80
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
74
81
 
@@ -147,7 +154,7 @@ onMounted(() => {
147
154
  </script>
148
155
 
149
156
  <template>
150
- <div :class="ui.root({ class: [props.class, props.ui?.root] })">
157
+ <Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
151
158
  <input
152
159
  :id="id"
153
160
  ref="inputRef"
@@ -159,10 +166,11 @@ onMounted(() => {
159
166
  :disabled="disabled"
160
167
  :required="required"
161
168
  :autocomplete="autocomplete"
162
- v-bind="$attrs"
169
+ v-bind="{ ...$attrs, ...ariaAttrs }"
163
170
  @input="onInput"
164
171
  @blur="onBlur"
165
172
  @change="onChange"
173
+ @focus="emitFormFocus"
166
174
  >
167
175
 
168
176
  <slot />
@@ -179,5 +187,5 @@ onMounted(() => {
179
187
  <UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
180
188
  </slot>
181
189
  </span>
182
- </div>
190
+ </Primitive>
183
191
  </template>
@@ -1,18 +1,18 @@
1
1
  <script lang="ts">
2
2
  import type { InputHTMLAttributes } from 'vue'
3
- import { tv, type VariantProps } from 'tailwind-variants'
4
- import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps } from 'radix-vue'
3
+ import type { VariantProps } from 'tailwind-variants'
4
+ import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
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
+ import { tv } from '../utils/tv'
10
10
  import type { AvatarProps, ChipProps, InputProps } from '../types'
11
- import type { AcceptableValue, ArrayOrWrapped, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
11
+ import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
12
12
 
13
- const appConfig = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
13
+ const appConfigInputMenu = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
14
14
 
15
- const inputMenu = tv({ extend: tv(theme), ...(appConfig.ui?.inputMenu || {}) })
15
+ const inputMenu = tv({ extend: tv(theme), ...(appConfigInputMenu.ui?.inputMenu || {}) })
16
16
 
17
17
  export interface InputMenuItem {
18
18
  label?: string
@@ -30,7 +30,7 @@ export interface InputMenuItem {
30
30
 
31
31
  type InputMenuVariants = VariantProps<typeof inputMenu>
32
32
 
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 {
33
+ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue | boolean> = MaybeArrayOfArray<InputMenuItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'highlightOnHover'>, UseComponentIconsProps {
34
34
  /**
35
35
  * The element or component this component should render as.
36
36
  * @defaultValue 'div'
@@ -64,7 +64,7 @@ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends Ma
64
64
  deleteIcon?: string
65
65
  /**
66
66
  * The content of the menu.
67
- * @defaultValue { side: 'bottom', sideOffset: 8, position: 'popper' }
67
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
68
68
  */
69
69
  content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
70
70
  /**
@@ -77,13 +77,6 @@ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends Ma
77
77
  * @defaultValue true
78
78
  */
79
79
  portal?: boolean
80
- /**
81
- * Whether to filter items or not, can be an array of fields to filter. Defaults to `[labelKey]`.
82
- * When `false`, items will not be filtered which is useful for custom filtering (useAsyncData, useFetch, etc.).
83
- * `['label']`{lang="ts-type"}
84
- * @defaultValue true
85
- */
86
- filter?: boolean | string[]
87
80
  /**
88
81
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
89
82
  * @defaultValue undefined
@@ -95,33 +88,45 @@ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends Ma
95
88
  */
96
89
  labelKey?: V
97
90
  items?: I
91
+ /** The value of the InputMenu when initially rendered. Use when you do not need to control the state of the InputMenu. */
92
+ defaultValue?: SelectModelValue<T, V, M>
93
+ /** The controlled value of the InputMenu. Can be binded-with with `v-model`. */
94
+ modelValue?: SelectModelValue<T, V, M>
95
+ /** Whether multiple options can be selected or not. */
96
+ multiple?: M & boolean
98
97
  /** Highlight the ring color like a focus state. */
99
98
  highlight?: boolean
100
99
  /**
101
100
  * Determines if custom user input that does not exist in options can be added.
102
101
  * @defaultValue false
103
102
  */
104
- createItem?: boolean | 'always' | { placement?: 'top' | 'bottom', when?: 'empty' | 'always' }
103
+ createItem?: boolean | 'always' | { position?: 'top' | 'bottom', when?: 'empty' | 'always' }
104
+ /**
105
+ * Fields to filter items by.
106
+ * @defaultValue [labelKey]
107
+ */
108
+ filterFields?: string[]
109
+ /**
110
+ * When `true`, disable the default filters, useful for custom filtering (useAsyncData, useFetch, etc.).
111
+ * @defaultValue false
112
+ */
113
+ ignoreFilter?: boolean
105
114
  class?: any
106
115
  ui?: PartialString<typeof inputMenu.slots>
107
- /** The controlled value of the Combobox. Can be binded-with with `v-model`. */
108
- modelValue?: SelectModelValue<T, V, M>
109
- /** Whether multiple options can be selected or not. */
110
- multiple?: M
111
116
  }
112
117
 
113
118
  export type InputMenuEmits<T, V, M extends boolean> = Omit<ComboboxRootEmits<T>, 'update:modelValue'> & {
114
119
  change: [payload: Event]
115
120
  blur: [payload: FocusEvent]
116
121
  focus: [payload: FocusEvent]
117
- create: [payload: Event, item: T]
122
+ create: [item: string]
118
123
  } & SelectModelValueEmits<T, V, M>
119
124
 
120
125
  type SlotProps<T> = (props: { item: T, index: number }) => any
121
126
 
122
- export interface InputMenuSlots<T> {
123
- 'leading'(props: { modelValue: T, open: boolean, ui: any }): any
124
- 'trailing'(props: { modelValue: T, open: boolean, ui: any }): any
127
+ export interface InputMenuSlots<T, M extends boolean> {
128
+ 'leading'(props: { modelValue?: M extends true ? T[] : T, open: boolean, ui: any }): any
129
+ 'trailing'(props: { modelValue?: M extends true ? T[] : T, open: boolean, ui: any }): any
125
130
  'empty'(props: { searchTerm?: string }): any
126
131
  'item': SlotProps<T>
127
132
  'item-leading': SlotProps<T>
@@ -129,15 +134,13 @@ export interface InputMenuSlots<T> {
129
134
  'item-trailing': SlotProps<T>
130
135
  'tags-item-text': SlotProps<T>
131
136
  'tags-item-delete': SlotProps<T>
132
- 'create-item-label'(props: { item: T }): any
137
+ 'create-item-label'(props: { item: string }): any
133
138
  }
134
-
135
- extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
136
139
  </script>
137
140
 
138
- <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">
141
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue | boolean> = MaybeArrayOfArray<InputMenuItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
139
142
  import { computed, ref, toRef, onMounted, toRaw } from 'vue'
140
- import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits } from 'radix-vue'
143
+ import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits, useFilter } from 'reka-ui'
141
144
  import { defu } from 'defu'
142
145
  import { isEqual } from 'ohash'
143
146
  import { reactivePick, createReusableTemplate } from '@vueuse/core'
@@ -146,7 +149,7 @@ import { useButtonGroup } from '../composables/useButtonGroup'
146
149
  import { useComponentIcons } from '../composables/useComponentIcons'
147
150
  import { useFormField } from '../composables/useFormField'
148
151
  import { useLocale } from '../composables/useLocale'
149
- import { get, escapeRegExp } from '../utils'
152
+ import { get, compare } from '../utils'
150
153
  import UIcon from './Icon.vue'
151
154
  import UAvatar from './Avatar.vue'
152
155
  import UChip from './Chip.vue'
@@ -157,30 +160,29 @@ const props = withDefaults(defineProps<InputMenuProps<T, I, V, M>>(), {
157
160
  type: 'text',
158
161
  autofocusDelay: 0,
159
162
  portal: true,
160
- filter: true,
161
163
  labelKey: 'label' as never
162
164
  })
163
165
  const emits = defineEmits<InputMenuEmits<T, V, M>>()
164
- const slots = defineSlots<InputMenuSlots<T>>()
166
+ const slots = defineSlots<InputMenuSlots<T, M>>()
165
167
 
166
168
  const searchTerm = defineModel<string>('searchTerm', { default: '' })
167
169
 
168
- const appConfig = useAppConfig()
169
170
  const { t } = useLocale()
170
- const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits)
171
- const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
171
+ const appConfig = useAppConfig()
172
+ const { contains } = useFilter({ sensitivity: 'base' })
173
+
174
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur', 'highlightOnHover', 'ignoreFilter'), emits)
175
+ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as ComboboxContentProps)
172
176
  const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
173
- // This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541)
174
- const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple)
175
177
 
176
- const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
178
+ const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField<InputProps>(props)
177
179
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
178
180
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
179
181
 
180
- const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
181
-
182
182
  const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)
183
183
 
184
+ const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
185
+
184
186
  const ui = computed(() => inputMenu({
185
187
  color: color.value,
186
188
  variant: props.variant,
@@ -189,7 +191,7 @@ const ui = computed(() => inputMenu({
189
191
  highlight: highlight.value,
190
192
  leading: isLeading.value || !!props.avatar || !!slots.leading,
191
193
  trailing: isTrailing.value || !!slots.trailing,
192
- multiple: multiple.value,
194
+ multiple: props.multiple,
193
195
  buttonGroup: orientation.value
194
196
  }))
195
197
 
@@ -198,69 +200,49 @@ function displayValue(value: T): string {
198
200
  return value && (typeof value === 'object' ? get(value, props.labelKey as string) : value)
199
201
  }
200
202
 
201
- const item = items.value.find(item => isEqual(get(item as Record<string, any>, props.valueKey as string), value))
202
-
203
+ const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
203
204
  return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
204
205
  }
205
206
 
206
- function filterFunction(
207
- inputItems: ArrayOrWrapped<T> = items.value as ArrayOrWrapped<T>,
208
- filterSearchTerm: string = searchTerm.value,
209
- comparator = (item: any, term: string) => String(item).search(new RegExp(term, 'i')) !== -1
210
- ): ArrayOrWrapped<T> {
211
- if (props.filter === false) {
212
- return inputItems
207
+ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as InputMenuItem[][] : [])
208
+ // eslint-disable-next-line vue/no-dupe-keys
209
+ const items = computed(() => groups.value.flatMap(group => group) as T[])
210
+
211
+ const filteredGroups = computed(() => {
212
+ if (props.ignoreFilter || !searchTerm.value) {
213
+ return groups.value
213
214
  }
214
215
 
215
- const fields = Array.isArray(props.filter) ? props.filter : [props.labelKey]
216
- const escapedSearchTerm = escapeRegExp(filterSearchTerm ?? '')
216
+ const fields = Array.isArray(props.filterFields) ? props.filterFields : [props.labelKey] as string[]
217
217
 
218
- return inputItems.filter((item) => {
218
+ return groups.value.map(items => items.filter((item) => {
219
219
  if (typeof item !== 'object') {
220
- return comparator(item, escapedSearchTerm)
220
+ return contains(item, searchTerm.value)
221
221
  }
222
222
 
223
- return fields.some((field) => {
224
- const child = get(item, field as string)
225
-
226
- return child !== null && child !== undefined && comparator(child, escapedSearchTerm)
227
- })
228
- }) as ArrayOrWrapped<T>
229
- }
230
-
231
- const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as InputMenuItem[][] : [])
232
- // eslint-disable-next-line vue/no-dupe-keys
233
- const items = computed(() => groups.value.flatMap(group => group) as T[])
234
-
235
- const creatable = computed(() => {
236
- if (!props.createItem) {
237
- return false
238
- }
223
+ if (item.type && ['label', 'separator'].includes(item.type)) {
224
+ return true
225
+ }
239
226
 
240
- const isModelValueCustom = props.modelValue && filterFunction((props.multiple && Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]) as ArrayOrWrapped<T>, searchTerm.value, (item, term) => String(item) === term).length === 1
227
+ return fields.some(field => contains(get(item, field), searchTerm.value))
228
+ })).filter(group => group.filter(item => !item.type || !['label', 'separator'].includes(item.type)).length > 0)
229
+ })
230
+ const filteredItems = computed(() => filteredGroups.value.flatMap(group => group) as T[])
241
231
 
242
- if (isModelValueCustom) {
232
+ const createItem = computed(() => {
233
+ if (!props.createItem || !searchTerm.value) {
243
234
  return false
244
235
  }
245
236
 
246
- const filteredItems = filterFunction()
247
- const newItem = searchTerm.value && {
248
- item: props.valueKey ? { [props.valueKey]: searchTerm.value, [props.labelKey ?? 'label']: searchTerm.value } : searchTerm.value,
249
- position: ((typeof props.createItem === 'object' && props.createItem.placement) || 'bottom') as 'top' | 'bottom'
250
- }
237
+ const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } as T : searchTerm.value
251
238
 
252
239
  if ((typeof props.createItem === 'object' && props.createItem.when === 'always') || props.createItem === 'always') {
253
- return (filteredItems.length === 1 && filterFunction(filteredItems, searchTerm.value, (item, term) => String(item) === term).length === 1) ? false : newItem
240
+ return !filteredItems.value.find(item => compare(item, newItem, props.valueKey))
254
241
  }
255
242
 
256
- return filteredItems.length > 0 ? false : newItem
243
+ return !filteredItems.value.length
257
244
  })
258
-
259
- const rootItems = computed(() => [
260
- ...(creatable.value && creatable.value.position === 'top' ? [creatable.value.item] : []),
261
- ...filterFunction(),
262
- ...(creatable.value && creatable.value.position === 'bottom' ? [creatable.value.item] : [])
263
- ] as ArrayOrWrapped<T>)
245
+ const createItemPosition = computed(() => typeof props.createItem === 'object' ? props.createItem.position : 'bottom')
264
246
 
265
247
  const inputRef = ref<InstanceType<typeof ComboboxInput> | null>(null)
266
248
 
@@ -294,6 +276,7 @@ function onBlur(event: FocusEvent) {
294
276
 
295
277
  function onFocus(event: FocusEvent) {
296
278
  emits('focus', event)
279
+ emitFormFocus()
297
280
  }
298
281
 
299
282
  function onUpdateOpen(value: boolean) {
@@ -307,22 +290,31 @@ function onUpdateOpen(value: boolean) {
307
290
  }
308
291
  }
309
292
 
293
+ function onRemoveTag(event: any) {
294
+ if (props.multiple) {
295
+ const modelValue = props.modelValue as SelectModelValue<T, V, true>
296
+ const filteredValue = modelValue.filter(value => !isEqual(value, event))
297
+ emits('update:modelValue', filteredValue as SelectModelValue<T, V, M>)
298
+ }
299
+ }
300
+
310
301
  defineExpose({
311
302
  inputRef
312
303
  })
313
304
  </script>
314
305
 
306
+ <!-- eslint-disable vue/no-template-shadow -->
315
307
  <template>
316
308
  <DefineCreateItemTemplate>
317
- <ComboboxGroup v-if="creatable" :class="ui.group({ class: props.ui?.group })">
309
+ <ComboboxGroup :class="ui.group({ class: props.ui?.group })">
318
310
  <ComboboxItem
319
311
  :class="ui.item({ class: props.ui?.item })"
320
- :value="valueKey && typeof creatable.item === 'object' ? get(creatable.item, props.valueKey as string) : creatable.item"
321
- @select="e => emits('create', e, (creatable as any).item as T)"
312
+ :value="searchTerm"
313
+ @select.prevent="emits('create', searchTerm)"
322
314
  >
323
315
  <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
324
- <slot name="create-item-label" :item="(creatable.item as T)">
325
- {{ t('inputMenu.create', { label: typeof creatable.item === 'object' ? get(creatable.item, props.labelKey as string) : creatable.item }) }}
316
+ <slot name="create-item-label" :item="searchTerm">
317
+ {{ t('inputMenu.create', { label: searchTerm }) }}
326
318
  </slot>
327
319
  </span>
328
320
  </ComboboxItem>
@@ -333,14 +325,11 @@ defineExpose({
333
325
  :id="id"
334
326
  v-slot="{ modelValue, open }"
335
327
  v-bind="rootProps"
336
- v-model:search-term="searchTerm"
337
328
  :name="name"
338
329
  :disabled="disabled"
339
- :multiple="multiple"
340
- :display-value="displayValue"
341
- :filter-function="() => rootItems"
342
330
  :class="ui.root({ class: [props.class, props.ui?.root] })"
343
331
  :as-child="!!multiple"
332
+ ignore-filter
344
333
  @update:model-value="onUpdate"
345
334
  @update:open="onUpdateOpen"
346
335
  @keydown.enter="$event.preventDefault()"
@@ -348,13 +337,14 @@ defineExpose({
348
337
  <ComboboxAnchor :as-child="!multiple" :class="ui.base({ class: props.ui?.base })">
349
338
  <TagsInputRoot
350
339
  v-if="multiple"
351
- v-slot="{ modelValue: tags }: { modelValue: AcceptableValue[] }"
340
+ v-slot="{ modelValue: tags }"
352
341
  :model-value="(modelValue as string[])"
353
342
  :disabled="disabled"
354
343
  delimiter=""
355
344
  as-child
356
345
  @blur="onBlur"
357
346
  @focus="onFocus"
347
+ @remove-tag="onRemoveTag"
358
348
  >
359
349
  <TagsInputItem v-for="(item, index) in tags" :key="index" :value="(item as string)" :class="ui.tagsItem({ class: props.ui?.tagsItem })">
360
350
  <TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
@@ -370,10 +360,10 @@ defineExpose({
370
360
  </TagsInputItemDelete>
371
361
  </TagsInputItem>
372
362
 
373
- <ComboboxInput as-child>
363
+ <ComboboxInput v-model="searchTerm" :display-value="displayValue" as-child>
374
364
  <TagsInputInput
375
365
  ref="inputRef"
376
- v-bind="$attrs"
366
+ v-bind="{ ...$attrs, ...ariaAttrs }"
377
367
  :placeholder="placeholder"
378
368
  :required="required"
379
369
  :class="ui.tagsInput({ class: props.ui?.tagsInput })"
@@ -385,24 +375,25 @@ defineExpose({
385
375
  <ComboboxInput
386
376
  v-else
387
377
  ref="inputRef"
388
- v-bind="$attrs"
378
+ v-model="searchTerm"
379
+ :display-value="displayValue"
380
+ v-bind="{ ...$attrs, ...ariaAttrs }"
389
381
  :type="type"
390
382
  :placeholder="placeholder"
391
383
  :required="required"
392
- :class="ui.base({ class: props.ui?.base })"
393
384
  @blur="onBlur"
394
385
  @focus="onFocus"
395
386
  />
396
387
 
397
388
  <span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
398
- <slot name="leading" :model-value="(modelValue as T)" :open="open" :ui="ui">
389
+ <slot name="leading" :model-value="(modelValue as M extends true ? T[] : T)" :open="open" :ui="ui">
399
390
  <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
400
391
  <UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
401
392
  </slot>
402
393
  </span>
403
394
 
404
395
  <ComboboxTrigger v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
405
- <slot name="trailing" :model-value="(modelValue as T)" :open="open" :ui="ui">
396
+ <slot name="trailing" :model-value="(modelValue as M extends true ? T[] : T)" :open="open" :ui="ui">
406
397
  <UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
407
398
  </slot>
408
399
  </ComboboxTrigger>
@@ -417,9 +408,9 @@ defineExpose({
417
408
  </ComboboxEmpty>
418
409
 
419
410
  <ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
420
- <ReuseCreateItemTemplate v-if="creatable && creatable.position === 'top'" />
411
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
421
412
 
422
- <ComboboxGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
413
+ <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
423
414
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
424
415
  <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
425
416
  {{ get(item, props.labelKey as string) }}
@@ -466,7 +457,7 @@ defineExpose({
466
457
  </template>
467
458
  </ComboboxGroup>
468
459
 
469
- <ReuseCreateItemTemplate v-if="creatable && creatable.position === 'bottom'" />
460
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
470
461
  </ComboboxViewport>
471
462
 
472
463
  <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
@@ -1,14 +1,16 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
3
- import type { NumberFieldRootProps } from 'radix-vue'
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { NumberFieldRootProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/input-number'
7
+ import { tv } from '../utils/tv'
7
8
  import type { ButtonProps } from '../types'
9
+ import type { PartialString } from '../types/utils'
8
10
 
9
- const appConfig = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
11
+ const appConfigInputNumber = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
10
12
 
11
- const inputNumber = tv({ extend: tv(theme), ...(appConfig.ui?.inputNumber || {}) })
13
+ const inputNumber = tv({ extend: tv(theme), ...(appConfigInputNumber.ui?.inputNumber || {}) })
12
14
 
13
15
  type InputNumberVariants = VariantProps<typeof inputNumber>
14
16
 
@@ -18,10 +20,8 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
18
20
  * @defaultValue 'div'
19
21
  */
20
22
  as?: any
21
- class?: any
22
23
  /** The placeholder text when the input is empty. */
23
24
  placeholder?: string
24
- ui?: Partial<typeof inputNumber.slots>
25
25
  color?: InputNumberVariants['color']
26
26
  variant?: InputNumberVariants['variant']
27
27
  size?: InputNumberVariants['size']
@@ -59,6 +59,8 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
59
59
  * @defaultValue UApp.locale.code
60
60
  */
61
61
  locale?: string
62
+ class?: any
63
+ ui?: PartialString<typeof inputNumber.slots>
62
64
  }
63
65
 
64
66
  export interface InputNumberEmits {
@@ -75,8 +77,9 @@ export interface InputNumberSlots {
75
77
 
76
78
  <script setup lang="ts">
77
79
  import { onMounted, ref, computed } from 'vue'
78
- import { NumberFieldRoot, NumberFieldInput, NumberFieldDecrement, NumberFieldIncrement, useForwardPropsEmits } from 'radix-vue'
80
+ import { NumberFieldRoot, NumberFieldInput, NumberFieldDecrement, NumberFieldIncrement, useForwardPropsEmits } from 'reka-ui'
79
81
  import { reactivePick } from '@vueuse/core'
82
+ import { useAppConfig } from '#imports'
80
83
  import { useFormField } from '../composables/useFormField'
81
84
  import { useLocale } from '../composables/useLocale'
82
85
  import UButton from './Button.vue'
@@ -91,7 +94,8 @@ defineSlots<InputNumberSlots>()
91
94
 
92
95
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emits)
93
96
 
94
- const { emitFormBlur, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled } = useFormField<InputNumberProps>(props)
97
+ const appConfig = useAppConfig()
98
+ const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
95
99
 
96
100
  const { t, code: codeLocale } = useLocale()
97
101
  const locale = computed(() => props.locale || codeLocale.value)
@@ -151,12 +155,13 @@ defineExpose({
151
155
  @update:model-value="onUpdate"
152
156
  >
153
157
  <NumberFieldInput
154
- v-bind="$attrs"
158
+ v-bind="{ ...$attrs, ...ariaAttrs }"
155
159
  ref="inputRef"
156
160
  :placeholder="placeholder"
157
161
  :required="required"
158
162
  :class="ui.base({ class: props.ui?.base })"
159
163
  @blur="onBlur"
164
+ @focus="emitFormFocus"
160
165
  />
161
166
 
162
167
  <div :class="ui.increment({ class: props.ui?.increment })">
@@ -1,14 +1,14 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import 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/kbd'
6
6
  import type { KbdKey } from '../composables/useKbd'
7
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
8
8
 
9
- const appConfig = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
9
+ const appConfigKbd = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
10
10
 
11
- const kbd = tv({ extend: tv(theme), ...(appConfig.ui?.kbd || {}) })
11
+ const kbd = tv({ extend: tv(theme), ...(appConfigKbd.ui?.kbd || {}) })
12
12
 
13
13
  type KbdVariants = VariantProps<typeof kbd>
14
14
 
@@ -27,11 +27,10 @@ export interface KbdProps {
27
27
  export interface KbdSlots {
28
28
  default(props?: {}): any
29
29
  }
30
- extendDevtoolsMeta({ defaultProps: { value: 'K' } })
31
30
  </script>
32
31
 
33
32
  <script setup lang="ts">
34
- import { Primitive } from 'radix-vue'
33
+ import { Primitive } from 'reka-ui'
35
34
  import { useKbd } from '../composables/useKbd'
36
35
 
37
36
  const props = withDefaults(defineProps<KbdProps>(), {
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
2
  import type { ButtonHTMLAttributes } from 'vue'
3
- import { tv } from 'tailwind-variants'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import _appConfig from '#build/app.config'
6
5
  import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
7
6
  import theme from '#build/ui/link'
8
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
9
8
 
10
9
  interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
11
10
  /**
@@ -53,9 +52,9 @@ interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
53
52
  noPrefetch?: boolean
54
53
  }
55
54
 
56
- const appConfig = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
55
+ const appConfigLink = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
57
56
 
58
- const link = tv({ extend: tv(theme), ...(appConfig.ui?.link || {}) })
57
+ const link = tv({ extend: tv(theme), ...(appConfigLink.ui?.link || {}) })
59
58
 
60
59
  export interface LinkProps extends NuxtLinkProps {
61
60
  /**
@@ -88,14 +87,12 @@ export interface LinkProps extends NuxtLinkProps {
88
87
  export interface LinkSlots {
89
88
  default(props: { active: boolean }): any
90
89
  }
91
-
92
- extendDevtoolsMeta({ example: 'LinkExample' })
93
90
  </script>
94
91
 
95
92
  <script setup lang="ts">
96
93
  import { computed } from 'vue'
97
94
  import { isEqual, diff } from 'ohash'
98
- import { useForwardProps } from 'radix-vue'
95
+ import { useForwardProps } from 'reka-ui'
99
96
  import { reactiveOmit } from '@vueuse/core'
100
97
  import { useRoute } from '#imports'
101
98
  import ULinkBase from './LinkBase.vue'
@@ -112,7 +109,7 @@ const props = withDefaults(defineProps<LinkProps>(), {
112
109
  defineSlots<LinkSlots>()
113
110
 
114
111
  const route = useRoute()
115
- const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass'))
112
+ const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'raw', 'class'))
116
113
 
117
114
  const ui = computed(() => tv({
118
115
  extend: link,