@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,17 +1,17 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
3
- import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps } from 'radix-vue'
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps, AcceptableValue } 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/select-menu'
7
7
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
9
9
  import type { AvatarProps, ChipProps, InputProps } from '../types'
10
- import type { AcceptableValue, ArrayOrWrapped, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
10
+ import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
11
11
 
12
- const appConfig = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
12
+ const appConfigSelectMenu = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
13
13
 
14
- const selectMenu = tv({ extend: tv(theme), ...(appConfig.ui?.selectMenu || {}) })
14
+ const selectMenu = tv({ extend: tv(theme), ...(appConfigSelectMenu.ui?.selectMenu || {}) })
15
15
 
16
16
  export interface SelectMenuItem {
17
17
  label?: string
@@ -29,7 +29,7 @@ export interface SelectMenuItem {
29
29
 
30
30
  type SelectMenuVariants = VariantProps<typeof selectMenu>
31
31
 
32
- export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'defaultValue' | 'selectedValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
32
+ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'highlightOnHover'>, UseComponentIconsProps {
33
33
  id?: string
34
34
  /** The placeholder text when the select is empty. */
35
35
  placeholder?: string
@@ -56,7 +56,7 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
56
56
  selectedIcon?: string
57
57
  /**
58
58
  * The content of the menu.
59
- * @defaultValue { side: 'bottom', sideOffset: 8, position: 'popper' }
59
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
60
60
  */
61
61
  content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
62
62
  /**
@@ -69,13 +69,6 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
69
69
  * @defaultValue true
70
70
  */
71
71
  portal?: boolean
72
- /**
73
- * Whether to filter items or not, can be an array of fields to filter. Defaults to `[labelKey]`.
74
- * When `false`, items will not be filtered which is useful for custom filtering (useAsyncData, useFetch, etc.).
75
- * `['label']`{lang="ts-type"}
76
- * @defaultValue true
77
- */
78
- filter?: boolean | string[]
79
72
  /**
80
73
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
81
74
  * @defaultValue undefined
@@ -87,94 +80,101 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
87
80
  */
88
81
  labelKey?: V
89
82
  items?: I
83
+ /** The value of the SelectMenu when initially rendered. Use when you do not need to control the state of the SelectMenu. */
84
+ defaultValue?: SelectModelValue<T, V, M>
85
+ /** The controlled value of the SelectMenu. Can be binded-with with `v-model`. */
86
+ modelValue?: SelectModelValue<T, V, M>
87
+ /** Whether multiple options can be selected or not. */
88
+ multiple?: M & boolean
90
89
  /** Highlight the ring color like a focus state. */
91
90
  highlight?: boolean
92
91
  /**
93
92
  * Determines if custom user input that does not exist in options can be added.
94
93
  * @defaultValue false
95
94
  */
96
- createItem?: boolean | 'always' | { placement?: 'top' | 'bottom', when?: 'empty' | 'always' }
95
+ createItem?: boolean | 'always' | { position?: 'top' | 'bottom', when?: 'empty' | 'always' }
96
+ /**
97
+ * Fields to filter items by.
98
+ * @defaultValue [labelKey]
99
+ */
100
+ filterFields?: string[]
101
+ /**
102
+ * When `true`, disable the default filters, useful for custom filtering (useAsyncData, useFetch, etc.).
103
+ * @defaultValue false
104
+ */
105
+ ignoreFilter?: boolean
97
106
  class?: any
98
107
  ui?: PartialString<typeof selectMenu.slots>
99
- /** The controlled value of the Combobox. Can be binded-with with `v-model`. */
100
- modelValue?: SelectModelValue<T, V, M>
101
- /** Whether multiple options can be selected or not. */
102
- multiple?: M
103
108
  }
104
109
 
105
110
  export type SelectMenuEmits<T, V, M extends boolean> = Omit<ComboboxRootEmits<T>, 'update:modelValue'> & {
106
111
  change: [payload: Event]
107
112
  blur: [payload: FocusEvent]
108
113
  focus: [payload: FocusEvent]
109
- create: [payload: Event, item: T]
114
+ create: [item: string]
110
115
  } & SelectModelValueEmits<T, V, M>
111
116
 
112
117
  type SlotProps<T> = (props: { item: T, index: number }) => any
113
118
 
114
- export interface SelectMenuSlots<T> {
115
- 'leading'(props: { modelValue: T, open: boolean, ui: any }): any
116
- 'default'(props: { modelValue: T, open: boolean }): any
117
- 'trailing'(props: { modelValue: T, open: boolean, ui: any }): any
119
+ export interface SelectMenuSlots<T, M extends boolean> {
120
+ 'leading'(props: { modelValue?: M extends true ? T[] : T, open: boolean, ui: any }): any
121
+ 'default'(props: { modelValue?: M extends true ? T[] : T, open: boolean }): any
122
+ 'trailing'(props: { modelValue?: M extends true ? T[] : T, open: boolean, ui: any }): any
118
123
  'empty'(props: { searchTerm?: string }): any
119
124
  'item': SlotProps<T>
120
125
  'item-leading': SlotProps<T>
121
126
  'item-label': SlotProps<T>
122
127
  'item-trailing': SlotProps<T>
123
- 'create-item-label'(props: { item: T }): any
128
+ 'create-item-label'(props: { item: string }): any
124
129
  }
125
-
126
- extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
127
130
  </script>
128
131
 
129
- <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
132
+ <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
130
133
  import { computed, toRef, toRaw } from 'vue'
131
- import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, useForwardPropsEmits } from 'radix-vue'
134
+ import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, FocusScope, useForwardPropsEmits, useFilter } from 'reka-ui'
132
135
  import { defu } from 'defu'
133
- import { isEqual } from 'ohash'
134
136
  import { reactivePick, createReusableTemplate } from '@vueuse/core'
135
137
  import { useAppConfig } from '#imports'
136
138
  import { useButtonGroup } from '../composables/useButtonGroup'
137
139
  import { useComponentIcons } from '../composables/useComponentIcons'
138
140
  import { useFormField } from '../composables/useFormField'
139
141
  import { useLocale } from '../composables/useLocale'
140
- import { get, escapeRegExp } from '../utils'
142
+ import { get, compare } from '../utils'
141
143
  import UIcon from './Icon.vue'
142
144
  import UAvatar from './Avatar.vue'
143
145
  import UChip from './Chip.vue'
144
146
  import UInput from './Input.vue'
145
147
 
148
+ defineOptions({ inheritAttrs: false })
149
+
146
150
  const props = withDefaults(defineProps<SelectMenuProps<T, I, V, M>>(), {
147
- search: true,
148
151
  portal: true,
149
- autofocusDelay: 0,
150
152
  searchInput: true,
151
- filter: true,
152
- labelKey: 'label' as never
153
+ labelKey: 'label' as never,
154
+ resetSearchTermOnBlur: true
153
155
  })
154
-
155
156
  const emits = defineEmits<SelectMenuEmits<T, V, M>>()
156
- const slots = defineSlots<SelectMenuSlots<T>>()
157
+ const slots = defineSlots<SelectMenuSlots<T, M>>()
157
158
 
158
159
  const searchTerm = defineModel<string>('searchTerm', { default: '' })
159
160
 
161
+ const { t } = useLocale()
160
162
  const appConfig = useAppConfig()
163
+ const { contains } = useFilter({ sensitivity: 'base' })
161
164
 
162
- const { t } = useLocale()
163
- const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits)
164
- const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
165
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur', 'highlightOnHover'), emits)
166
+ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as ComboboxContentProps)
165
167
  const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
166
- const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: 'Search...', variant: 'none' }) as InputProps)
167
- // This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541)
168
- const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple)
169
-
170
- const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
168
+ const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: t('selectMenu.search'), variant: 'none' }) as InputProps)
171
169
 
172
- const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
170
+ const { emitFormBlur, emitFormFocus, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField<InputProps>(props)
173
171
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
174
172
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
175
173
 
176
174
  const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
177
175
 
176
+ const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
177
+
178
178
  const ui = computed(() => selectMenu({
179
179
  color: color.value,
180
180
  variant: props.variant,
@@ -187,7 +187,7 @@ const ui = computed(() => selectMenu({
187
187
  }))
188
188
 
189
189
  function displayValue(value: T | T[]): string {
190
- if (multiple.value && Array.isArray(value)) {
190
+ if (props.multiple && Array.isArray(value)) {
191
191
  return value.map(v => displayValue(v)).filter(Boolean).join(', ')
192
192
  }
193
193
 
@@ -195,69 +195,49 @@ function displayValue(value: T | T[]): string {
195
195
  return value && (typeof value === 'object' ? get(value, props.labelKey as string) : value)
196
196
  }
197
197
 
198
- const item = items.value.find(item => isEqual(get(item as Record<string, any>, props.valueKey as string), value)) ?? (props.createItem && value)
199
-
198
+ const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
200
199
  return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
201
200
  }
202
201
 
203
- function filterFunction(
204
- inputItems: ArrayOrWrapped<T> = items.value as ArrayOrWrapped<T>,
205
- filterSearchTerm: string = searchTerm.value,
206
- comparator = (item: any, term: string) => String(item).search(new RegExp(term, 'i')) !== -1
207
- ): ArrayOrWrapped<T> {
208
- if (props.filter === false) {
209
- return inputItems
202
+ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as SelectMenuItem[][] : [])
203
+ // eslint-disable-next-line vue/no-dupe-keys
204
+ const items = computed(() => groups.value.flatMap(group => group) as T[])
205
+
206
+ const filteredGroups = computed(() => {
207
+ if (props.ignoreFilter || !searchTerm.value) {
208
+ return groups.value
210
209
  }
211
210
 
212
- const fields = Array.isArray(props.filter) ? props.filter : [props.labelKey]
213
- const escapedSearchTerm = escapeRegExp(filterSearchTerm)
211
+ const fields = Array.isArray(props.filterFields) ? props.filterFields : [props.labelKey] as string[]
214
212
 
215
- return inputItems.filter((item: T) => {
213
+ return groups.value.map(items => items.filter((item) => {
216
214
  if (typeof item !== 'object') {
217
- return comparator(item, escapedSearchTerm)
215
+ return contains(item, searchTerm.value)
218
216
  }
219
217
 
220
- return fields.some((field) => {
221
- const child = get(item, field as string)
222
-
223
- return child !== null && child !== undefined && comparator(child, escapedSearchTerm)
224
- })
225
- }) as ArrayOrWrapped<T>
226
- }
227
-
228
- const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as SelectMenuItem[][] : [])
229
- // eslint-disable-next-line vue/no-dupe-keys
230
- const items = computed(() => groups.value.flatMap(group => group) as T[])
231
-
232
- const creatable = computed(() => {
233
- if (!props.createItem) {
234
- return false
235
- }
218
+ if (item.type && ['label', 'separator'].includes(item.type)) {
219
+ return true
220
+ }
236
221
 
237
- 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
222
+ return fields.some(field => contains(get(item, field), searchTerm.value))
223
+ })).filter(group => group.filter(item => !item.type || !['label', 'separator'].includes(item.type)).length > 0)
224
+ })
225
+ const filteredItems = computed(() => filteredGroups.value.flatMap(group => group) as T[])
238
226
 
239
- if (isModelValueCustom) {
227
+ const createItem = computed(() => {
228
+ if (!props.createItem || !searchTerm.value) {
240
229
  return false
241
230
  }
242
231
 
243
- const filteredItems = filterFunction()
244
- const newItem = searchTerm.value && {
245
- item: props.valueKey ? { [props.valueKey]: searchTerm.value, [props.labelKey ?? 'label']: searchTerm.value } : searchTerm.value,
246
- position: ((typeof props.createItem === 'object' && props.createItem.placement) || 'bottom') as 'top' | 'bottom'
247
- }
232
+ const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } as T : searchTerm.value
248
233
 
249
234
  if ((typeof props.createItem === 'object' && props.createItem.when === 'always') || props.createItem === 'always') {
250
- return (filteredItems.length === 1 && filterFunction(filteredItems, searchTerm.value, (item, term) => String(item) === term).length === 1) ? false : newItem
235
+ return !filteredItems.value.find(item => compare(item, newItem, props.valueKey))
251
236
  }
252
237
 
253
- return filteredItems.length > 0 ? false : newItem
238
+ return !filteredItems.value.length
254
239
  })
255
-
256
- const rootItems = computed(() => [
257
- ...(creatable.value && creatable.value.position === 'top' ? [creatable.value.item] : []),
258
- ...filterFunction(),
259
- ...(creatable.value && creatable.value.position === 'bottom' ? [creatable.value.item] : [])
260
- ] as ArrayOrWrapped<T>)
240
+ const createItemPosition = computed(() => typeof props.createItem === 'object' ? props.createItem.position : 'bottom')
261
241
 
262
242
  function onUpdate(value: any) {
263
243
  if (toRaw(props.modelValue) === value) {
@@ -271,28 +251,44 @@ function onUpdate(value: any) {
271
251
  }
272
252
 
273
253
  function onUpdateOpen(value: boolean) {
254
+ let timeoutId
255
+
274
256
  if (!value) {
275
257
  const event = new FocusEvent('blur')
258
+
276
259
  emits('blur', event)
277
260
  emitFormBlur()
261
+
262
+ // Since we use `displayValue` prop inside ComboboxInput we should reset searchTerm manually
263
+ // https://reka-ui.com/docs/components/combobox#api-reference
264
+ if (props.resetSearchTermOnBlur) {
265
+ const STATE_ANIMATION_DELAY_MS = 100
266
+
267
+ timeoutId = setTimeout(() => {
268
+ searchTerm.value = ''
269
+ }, STATE_ANIMATION_DELAY_MS)
270
+ }
278
271
  } else {
279
272
  const event = new FocusEvent('focus')
280
273
  emits('focus', event)
274
+ emitFormFocus()
275
+ clearTimeout(timeoutId)
281
276
  }
282
277
  }
283
278
  </script>
284
279
 
280
+ <!-- eslint-disable vue/no-template-shadow -->
285
281
  <template>
286
282
  <DefineCreateItemTemplate>
287
- <ComboboxGroup v-if="creatable" :class="ui.group({ class: props.ui?.group })">
283
+ <ComboboxGroup :class="ui.group({ class: props.ui?.group })">
288
284
  <ComboboxItem
289
285
  :class="ui.item({ class: props.ui?.item })"
290
- :value="valueKey && typeof creatable.item === 'object' ? get(creatable.item, props.valueKey as string) : creatable.item"
291
- @select="e => emits('create', e, (creatable as any).item as T)"
286
+ :value="searchTerm"
287
+ @select.prevent="emits('create', searchTerm)"
292
288
  >
293
289
  <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
294
- <slot name="create-item-label" :item="(creatable.item as T)">
295
- {{ t('selectMenu.create', { label: typeof creatable.item === 'object' ? get(creatable.item, props.labelKey as string) : creatable.item }) }}
290
+ <slot name="create-item-label" :item="searchTerm">
291
+ {{ t('selectMenu.create', { label: searchTerm }) }}
296
292
  </slot>
297
293
  </span>
298
294
  </ComboboxItem>
@@ -302,28 +298,25 @@ function onUpdateOpen(value: boolean) {
302
298
  <ComboboxRoot
303
299
  :id="id"
304
300
  v-slot="{ modelValue, open }"
305
- v-bind="rootProps"
306
- v-model:search-term="searchTerm"
301
+ v-bind="{ ...rootProps, ...$attrs, ...ariaAttrs }"
302
+ ignore-filter
307
303
  as-child
308
304
  :name="name"
309
305
  :disabled="disabled"
310
- :multiple="multiple"
311
- :display-value="() => searchTerm"
312
- :filter-function="() => rootItems"
313
306
  @update:model-value="onUpdate"
314
307
  @update:open="onUpdateOpen"
315
308
  >
316
309
  <ComboboxAnchor as-child>
317
310
  <ComboboxTrigger :class="ui.base({ class: [props.class, props.ui?.base] })" tabindex="0">
318
311
  <span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
319
- <slot name="leading" :model-value="(modelValue as T)" :open="open" :ui="ui">
312
+ <slot name="leading" :model-value="(modelValue as M extends true ? T[] : T)" :open="open" :ui="ui">
320
313
  <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
321
314
  <UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
322
315
  </slot>
323
316
  </span>
324
317
 
325
- <slot :model-value="(modelValue as T)" :open="open">
326
- <template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
318
+ <slot :model-value="(modelValue as M extends true ? T[] : T)" :open="open">
319
+ <template v-for="displayedModelValue in [displayValue(modelValue as M extends true ? T[] : T)]" :key="displayedModelValue">
327
320
  <span v-if="displayedModelValue" :class="ui.value({ class: props.ui?.value })">
328
321
  {{ displayedModelValue }}
329
322
  </span>
@@ -334,7 +327,7 @@ function onUpdateOpen(value: boolean) {
334
327
  </slot>
335
328
 
336
329
  <span v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
337
- <slot name="trailing" :model-value="(modelValue as T)" :open="open" :ui="ui">
330
+ <slot name="trailing" :model-value="(modelValue as M extends true ? T[] : T)" :open="open" :ui="ui">
338
331
  <UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
339
332
  </slot>
340
333
  </span>
@@ -343,68 +336,70 @@ function onUpdateOpen(value: boolean) {
343
336
 
344
337
  <ComboboxPortal :disabled="!portal">
345
338
  <ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
346
- <ComboboxInput v-if="!!searchInput" as-child>
347
- <UInput autofocus autocomplete="off" v-bind="searchInputProps" :class="ui.input({ class: props.ui?.input })" />
348
- </ComboboxInput>
339
+ <FocusScope trapped :class="ui.focusScope({ class: props.ui?.focusScope })">
340
+ <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
341
+ <UInput autofocus autocomplete="off" v-bind="searchInputProps" :class="ui.input({ class: props.ui?.input })" />
342
+ </ComboboxInput>
343
+
344
+ <ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
345
+ <slot name="empty" :search-term="searchTerm">
346
+ {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
347
+ </slot>
348
+ </ComboboxEmpty>
349
+
350
+ <ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
351
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
352
+
353
+ <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
354
+ <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
355
+ <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
356
+ {{ get(item, props.labelKey as string) }}
357
+ </ComboboxLabel>
358
+
359
+ <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
360
+
361
+ <ComboboxItem
362
+ v-else
363
+ :class="ui.item({ class: props.ui?.item })"
364
+ :disabled="item.disabled"
365
+ :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
366
+ @select="item.onSelect"
367
+ >
368
+ <slot name="item" :item="(item as T)" :index="index">
369
+ <slot name="item-leading" :item="(item as T)" :index="index">
370
+ <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
371
+ <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 })" />
372
+ <UChip
373
+ v-else-if="item.chip"
374
+ :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
375
+ inset
376
+ standalone
377
+ v-bind="item.chip"
378
+ :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
379
+ />
380
+ </slot>
349
381
 
350
- <ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
351
- <slot name="empty" :search-term="searchTerm">
352
- {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
353
- </slot>
354
- </ComboboxEmpty>
355
-
356
- <ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
357
- <ReuseCreateItemTemplate v-if="creatable && creatable.position === 'top'" />
358
-
359
- <ComboboxGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
360
- <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
361
- <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
362
- {{ get(item, props.labelKey as string) }}
363
- </ComboboxLabel>
364
-
365
- <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
366
-
367
- <ComboboxItem
368
- v-else
369
- :class="ui.item({ class: props.ui?.item })"
370
- :disabled="item.disabled"
371
- :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
372
- @select="item.onSelect"
373
- >
374
- <slot name="item" :item="(item as T)" :index="index">
375
- <slot name="item-leading" :item="(item as T)" :index="index">
376
- <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
377
- <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 })" />
378
- <UChip
379
- v-else-if="item.chip"
380
- :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
381
- inset
382
- standalone
383
- v-bind="item.chip"
384
- :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
385
- />
382
+ <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
383
+ <slot name="item-label" :item="(item as T)" :index="index">
384
+ {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
385
+ </slot>
386
+ </span>
387
+
388
+ <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
389
+ <slot name="item-trailing" :item="(item as T)" :index="index" />
390
+
391
+ <ComboboxItemIndicator as-child>
392
+ <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
393
+ </ComboboxItemIndicator>
394
+ </span>
386
395
  </slot>
396
+ </ComboboxItem>
397
+ </template>
398
+ </ComboboxGroup>
387
399
 
388
- <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
389
- <slot name="item-label" :item="(item as T)" :index="index">
390
- {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
391
- </slot>
392
- </span>
393
-
394
- <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
395
- <slot name="item-trailing" :item="(item as T)" :index="index" />
396
-
397
- <ComboboxItemIndicator as-child>
398
- <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
399
- </ComboboxItemIndicator>
400
- </span>
401
- </slot>
402
- </ComboboxItem>
403
- </template>
404
- </ComboboxGroup>
405
-
406
- <ReuseCreateItemTemplate v-if="creatable && creatable.position === 'bottom'" />
407
- </ComboboxViewport>
400
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
401
+ </ComboboxViewport>
402
+ </FocusScope>
408
403
 
409
404
  <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
410
405
  </ComboboxContent>
@@ -1,14 +1,15 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
3
- import type { SeparatorProps as _SeparatorProps } from 'radix-vue'
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { SeparatorProps as _SeparatorProps } 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/separator'
7
+ import { tv } from '../utils/tv'
7
8
  import type { AvatarProps } from '../types'
8
9
 
9
- const appConfig = _appConfig as AppConfig & { ui: { separator: Partial<typeof theme> } }
10
+ const appConfigSeparator = _appConfig as AppConfig & { ui: { separator: Partial<typeof theme> } }
10
11
 
11
- const separator = tv({ extend: tv(theme), ...(appConfig.ui?.separator || {}) })
12
+ const separator = tv({ extend: tv(theme), ...(appConfigSeparator.ui?.separator || {}) })
12
13
 
13
14
  type SeparatorVariants = VariantProps<typeof separator>
14
15
 
@@ -43,7 +44,7 @@ export interface SeparatorSlots {
43
44
 
44
45
  <script setup lang="ts">
45
46
  import { computed } from 'vue'
46
- import { Separator, useForwardProps } from 'radix-vue'
47
+ import { Separator, useForwardProps } from 'reka-ui'
47
48
  import { reactivePick } from '@vueuse/core'
48
49
  import UIcon from './Icon.vue'
49
50
  import UAvatar from './Avatar.vue'
@@ -1,13 +1,12 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { AppConfig } from '@nuxt/schema'
4
3
  import _appConfig from '#build/app.config'
5
4
  import theme from '#build/ui/skeleton'
6
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
5
+ import { tv } from '../utils/tv'
7
6
 
8
- const appConfig = _appConfig as AppConfig & { ui: { skeleton: Partial<typeof theme> } }
7
+ const appConfigSkeleton = _appConfig as AppConfig & { ui: { skeleton: Partial<typeof theme> } }
9
8
 
10
- const skeleton = tv({ extend: tv(theme), ...(appConfig.ui?.skeleton || {}) })
9
+ const skeleton = tv({ extend: tv(theme), ...(appConfigSkeleton.ui?.skeleton || {}) })
11
10
 
12
11
  export interface SkeletonProps {
13
12
  /**
@@ -17,12 +16,10 @@ export interface SkeletonProps {
17
16
  as?: any
18
17
  class?: any
19
18
  }
20
-
21
- extendDevtoolsMeta({ example: 'SkeletonExample' })
22
19
  </script>
23
20
 
24
21
  <script setup lang="ts">
25
- import { Primitive } from 'radix-vue'
22
+ import { Primitive } from 'reka-ui'
26
23
 
27
24
  const props = defineProps<SkeletonProps>()
28
25
  </script>