@nuxt/ui 3.0.1 → 3.1.0

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 (228) hide show
  1. package/.nuxt/ui/accordion.ts +25 -4
  2. package/.nuxt/ui/alert.ts +52 -31
  3. package/.nuxt/ui/avatar-group.ts +24 -3
  4. package/.nuxt/ui/avatar.ts +26 -5
  5. package/.nuxt/ui/badge.ts +56 -35
  6. package/.nuxt/ui/breadcrumb.ts +28 -7
  7. package/.nuxt/ui/button-group.ts +23 -2
  8. package/.nuxt/ui/button.ts +66 -45
  9. package/.nuxt/ui/calendar.ts +39 -18
  10. package/.nuxt/ui/card.ts +28 -7
  11. package/.nuxt/ui/carousel.ts +29 -8
  12. package/.nuxt/ui/checkbox-group.ts +82 -0
  13. package/.nuxt/ui/checkbox.ts +163 -29
  14. package/.nuxt/ui/chip.ts +31 -10
  15. package/.nuxt/ui/collapsible.ts +23 -2
  16. package/.nuxt/ui/color-picker.ts +26 -5
  17. package/.nuxt/ui/command-palette.ts +37 -16
  18. package/.nuxt/ui/container.ts +24 -3
  19. package/.nuxt/ui/context-menu.ts +56 -35
  20. package/.nuxt/ui/drawer.ts +33 -12
  21. package/.nuxt/ui/dropdown-menu.ts +57 -36
  22. package/.nuxt/ui/form-field.ts +29 -8
  23. package/.nuxt/ui/form.ts +23 -2
  24. package/.nuxt/ui/index.ts +1 -0
  25. package/.nuxt/ui/input-menu.ts +65 -44
  26. package/.nuxt/ui/input-number.ts +43 -22
  27. package/.nuxt/ui/input.ts +46 -25
  28. package/.nuxt/ui/kbd.ts +27 -6
  29. package/.nuxt/ui/link.ts +26 -5
  30. package/.nuxt/ui/modal.ts +28 -7
  31. package/.nuxt/ui/navigation-menu.ts +103 -84
  32. package/.nuxt/ui/pagination.ts +23 -2
  33. package/.nuxt/ui/pin-input.ts +43 -22
  34. package/.nuxt/ui/popover.ts +25 -4
  35. package/.nuxt/ui/progress.ts +40 -19
  36. package/.nuxt/ui/radio-group.ts +273 -37
  37. package/.nuxt/ui/select-menu.ts +59 -35
  38. package/.nuxt/ui/select.ts +55 -34
  39. package/.nuxt/ui/separator.ts +31 -10
  40. package/.nuxt/ui/skeleton.ts +24 -3
  41. package/.nuxt/ui/slideover.ts +27 -6
  42. package/.nuxt/ui/slider.ts +39 -18
  43. package/.nuxt/ui/stepper.ts +41 -20
  44. package/.nuxt/ui/switch.ts +44 -23
  45. package/.nuxt/ui/table.ts +38 -17
  46. package/.nuxt/ui/tabs.ts +55 -34
  47. package/.nuxt/ui/textarea.ts +63 -37
  48. package/.nuxt/ui/toast.ts +47 -26
  49. package/.nuxt/ui/toaster.ts +23 -2
  50. package/.nuxt/ui/tooltip.ts +25 -4
  51. package/.nuxt/ui/tree.ts +41 -20
  52. package/.nuxt/ui.css +56 -12
  53. package/README.md +11 -0
  54. package/cli/templates.mjs +18 -17
  55. package/dist/module.d.mts +2 -1
  56. package/dist/module.json +5 -5
  57. package/dist/module.mjs +11 -7
  58. package/dist/runtime/components/Accordion.vue +36 -92
  59. package/dist/runtime/components/Accordion.vue.d.ts +91 -0
  60. package/dist/runtime/components/Alert.vue +37 -100
  61. package/dist/runtime/components/Alert.vue.d.ts +96 -0
  62. package/dist/runtime/components/App.vue +28 -34
  63. package/dist/runtime/components/App.vue.d.ts +24 -0
  64. package/dist/runtime/components/Avatar.vue +47 -78
  65. package/dist/runtime/components/Avatar.vue.d.ts +60 -0
  66. package/dist/runtime/components/AvatarGroup.vue +40 -77
  67. package/dist/runtime/components/AvatarGroup.vue.d.ts +40 -0
  68. package/dist/runtime/components/Badge.vue +33 -62
  69. package/dist/runtime/components/Badge.vue.d.ts +62 -0
  70. package/dist/runtime/components/Breadcrumb.vue +36 -88
  71. package/dist/runtime/components/Breadcrumb.vue.d.ts +82 -0
  72. package/dist/runtime/components/Button.vue +96 -105
  73. package/dist/runtime/components/Button.vue.d.ts +73 -0
  74. package/dist/runtime/components/ButtonGroup.vue +20 -46
  75. package/dist/runtime/components/ButtonGroup.vue.d.ts +55 -0
  76. package/dist/runtime/components/Calendar.vue +73 -127
  77. package/dist/runtime/components/Calendar.vue.d.ts +107 -0
  78. package/dist/runtime/components/Card.vue +18 -40
  79. package/dist/runtime/components/Card.vue.d.ts +38 -0
  80. package/dist/runtime/components/Carousel.vue +112 -230
  81. package/dist/runtime/components/Carousel.vue.d.ts +120 -0
  82. package/dist/runtime/components/Checkbox.vue +52 -93
  83. package/dist/runtime/components/Checkbox.vue.d.ts +76 -0
  84. package/dist/runtime/components/CheckboxGroup.vue +121 -0
  85. package/dist/runtime/components/CheckboxGroup.vue.d.ts +75 -0
  86. package/dist/runtime/components/Chip.vue +26 -69
  87. package/dist/runtime/components/Chip.vue.d.ts +71 -0
  88. package/dist/runtime/components/Collapsible.vue +22 -41
  89. package/dist/runtime/components/Collapsible.vue.d.ts +50 -0
  90. package/dist/runtime/components/ColorPicker.vue +111 -197
  91. package/dist/runtime/components/ColorPicker.vue.d.ts +63 -0
  92. package/dist/runtime/components/CommandPalette.vue +94 -234
  93. package/dist/runtime/components/CommandPalette.vue.d.ts +173 -0
  94. package/dist/runtime/components/Container.vue +15 -28
  95. package/dist/runtime/components/Container.vue.d.ts +27 -0
  96. package/dist/runtime/components/ContextMenu.vue +32 -119
  97. package/dist/runtime/components/ContextMenu.vue.d.ts +127 -0
  98. package/dist/runtime/components/ContextMenuContent.vue +71 -72
  99. package/dist/runtime/components/ContextMenuContent.vue.d.ts +105 -0
  100. package/dist/runtime/components/Drawer.vue +49 -87
  101. package/dist/runtime/components/Drawer.vue.d.ts +88 -0
  102. package/dist/runtime/components/DropdownMenu.vue +37 -129
  103. package/dist/runtime/components/DropdownMenu.vue.d.ts +141 -0
  104. package/dist/runtime/components/DropdownMenuContent.vue +76 -79
  105. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +55 -0
  106. package/dist/runtime/components/Form.vue +135 -219
  107. package/dist/runtime/components/Form.vue.d.ts +66 -0
  108. package/dist/runtime/components/FormField.vue +36 -77
  109. package/dist/runtime/components/FormField.vue.d.ts +70 -0
  110. package/dist/runtime/components/Icon.vue +12 -19
  111. package/dist/runtime/components/Icon.vue.d.ts +17 -0
  112. package/dist/runtime/components/Input.vue +82 -140
  113. package/dist/runtime/components/Input.vue.d.ts +91 -0
  114. package/dist/runtime/components/InputMenu.vue +193 -302
  115. package/dist/runtime/components/InputMenu.vue.d.ts +312 -0
  116. package/dist/runtime/components/InputNumber.vue +71 -133
  117. package/dist/runtime/components/InputNumber.vue.d.ts +193 -0
  118. package/dist/runtime/components/Kbd.vue +20 -46
  119. package/dist/runtime/components/Kbd.vue.d.ts +55 -0
  120. package/dist/runtime/components/Link.vue +98 -173
  121. package/dist/runtime/components/Link.vue.d.ts +124 -0
  122. package/dist/runtime/components/LinkBase.vue +33 -41
  123. package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
  124. package/dist/runtime/components/Modal.vue +53 -116
  125. package/dist/runtime/components/Modal.vue.d.ts +109 -0
  126. package/dist/runtime/components/NavigationMenu.vue +78 -186
  127. package/dist/runtime/components/NavigationMenu.vue.d.ts +159 -0
  128. package/dist/runtime/components/OverlayProvider.vue +14 -18
  129. package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
  130. package/dist/runtime/components/Pagination.vue +46 -140
  131. package/dist/runtime/components/Pagination.vue.d.ts +143 -0
  132. package/dist/runtime/components/PinInput.vue +61 -78
  133. package/dist/runtime/components/PinInput.vue.d.ts +68 -0
  134. package/dist/runtime/components/Popover.vue +47 -84
  135. package/dist/runtime/components/Popover.vue.d.ts +80 -0
  136. package/dist/runtime/components/Progress.vue +70 -131
  137. package/dist/runtime/components/Progress.vue.d.ts +97 -0
  138. package/dist/runtime/components/RadioGroup.vue +75 -126
  139. package/dist/runtime/components/RadioGroup.vue.d.ts +88 -0
  140. package/dist/runtime/components/Select.vue +115 -202
  141. package/dist/runtime/components/Select.vue.d.ts +139 -0
  142. package/dist/runtime/components/SelectMenu.vue +167 -281
  143. package/dist/runtime/components/SelectMenu.vue.d.ts +184 -0
  144. package/dist/runtime/components/Separator.vue +29 -71
  145. package/dist/runtime/components/Separator.vue.d.ts +75 -0
  146. package/dist/runtime/components/Skeleton.vue +21 -23
  147. package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
  148. package/dist/runtime/components/Slideover.vue +53 -120
  149. package/dist/runtime/components/Slideover.vue.d.ts +111 -0
  150. package/dist/runtime/components/Slider.vue +46 -84
  151. package/dist/runtime/components/Slider.vue.d.ts +71 -0
  152. package/dist/runtime/components/Stepper.vue +44 -113
  153. package/dist/runtime/components/Stepper.vue.d.ts +89 -0
  154. package/dist/runtime/components/Switch.vue +45 -93
  155. package/dist/runtime/components/Switch.vue.d.ts +73 -0
  156. package/dist/runtime/components/Table.vue +165 -264
  157. package/dist/runtime/components/Table.vue.d.ts +183 -0
  158. package/dist/runtime/components/Tabs.vue +40 -105
  159. package/dist/runtime/components/Tabs.vue.d.ts +104 -0
  160. package/dist/runtime/components/Textarea.vue +113 -158
  161. package/dist/runtime/components/Textarea.vue.d.ts +95 -0
  162. package/dist/runtime/components/Toast.vue +49 -110
  163. package/dist/runtime/components/Toast.vue.d.ts +95 -0
  164. package/dist/runtime/components/Toaster.vue +70 -107
  165. package/dist/runtime/components/Toaster.vue.d.ts +63 -0
  166. package/dist/runtime/components/Tooltip.vue +38 -65
  167. package/dist/runtime/components/Tooltip.vue.d.ts +65 -0
  168. package/dist/runtime/components/Tree.vue +57 -150
  169. package/dist/runtime/components/Tree.vue.d.ts +128 -0
  170. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  171. package/dist/runtime/composables/defineShortcuts.js +0 -1
  172. package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
  173. package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
  174. package/dist/runtime/composables/useFormField.d.ts +2 -2
  175. package/dist/runtime/composables/useFormField.js +1 -1
  176. package/dist/runtime/composables/useOverlay.d.ts +16 -8
  177. package/dist/runtime/composables/useOverlay.js +14 -6
  178. package/dist/runtime/composables/usePortal.d.ts +6 -0
  179. package/dist/runtime/composables/usePortal.js +17 -0
  180. package/dist/runtime/index.css +1 -1
  181. package/dist/runtime/inertia/components/Link.vue +146 -0
  182. package/dist/runtime/inertia/components/Link.vue.d.ts +92 -0
  183. package/dist/runtime/inertia/stubs.d.ts +43 -0
  184. package/dist/runtime/inertia/stubs.js +82 -0
  185. package/dist/runtime/locale/bg.d.ts +3 -0
  186. package/dist/runtime/locale/bg.js +54 -0
  187. package/dist/runtime/locale/hy.d.ts +3 -0
  188. package/dist/runtime/locale/hy.js +54 -0
  189. package/dist/runtime/locale/index.d.ts +6 -1
  190. package/dist/runtime/locale/index.js +6 -1
  191. package/dist/runtime/locale/kk.d.ts +3 -0
  192. package/dist/runtime/locale/kk.js +54 -0
  193. package/dist/runtime/locale/tj.d.ts +3 -0
  194. package/dist/runtime/locale/tj.js +54 -0
  195. package/dist/runtime/locale/ug_cn.d.ts +3 -0
  196. package/dist/runtime/locale/ug_cn.js +55 -0
  197. package/dist/runtime/types/form.d.ts +5 -1
  198. package/dist/runtime/types/index.d.ts +2 -0
  199. package/dist/runtime/types/index.js +2 -0
  200. package/dist/runtime/types/utils.d.ts +70 -10
  201. package/dist/runtime/utils/index.d.ts +1 -0
  202. package/dist/runtime/utils/index.js +3 -0
  203. package/dist/runtime/utils/link.d.ts +4 -27
  204. package/dist/runtime/utils/link.js +32 -1
  205. package/dist/runtime/utils/tv.js +2 -2
  206. package/dist/runtime/vue/components/Icon.vue +7 -8
  207. package/dist/runtime/vue/components/Icon.vue.d.ts +14 -0
  208. package/dist/runtime/vue/components/Link.vue +118 -199
  209. package/dist/runtime/vue/components/Link.vue.d.ts +124 -0
  210. package/dist/runtime/vue/stubs.d.ts +5 -0
  211. package/dist/runtime/vue/stubs.js +11 -2
  212. package/dist/shared/{ui.BCaWD5Ek.mjs → ui.D7lOOabO.mjs} +623 -364
  213. package/dist/types.d.mts +5 -1
  214. package/dist/unplugin.d.mts +6 -1
  215. package/dist/unplugin.mjs +25 -4
  216. package/dist/vite.mjs +1 -1
  217. package/package.json +122 -64
  218. package/dist/module.cjs +0 -62
  219. package/dist/module.d.cts +0 -44
  220. package/dist/module.d.ts +0 -44
  221. package/dist/shared/ui.C6uTSFTI.cjs +0 -3555
  222. package/dist/types.d.ts +0 -1
  223. package/dist/unplugin.cjs +0 -232
  224. package/dist/unplugin.d.cts +0 -61
  225. package/dist/unplugin.d.ts +0 -61
  226. package/dist/vite.cjs +0 -23
  227. package/dist/vite.d.cts +0 -15
  228. package/dist/vite.d.ts +0 -15
@@ -1,158 +1,69 @@
1
- <script lang="ts">
2
- import type { VariantProps } from 'tailwind-variants'
3
- import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps, AcceptableValue } from 'reka-ui'
4
- import type { AppConfig } from '@nuxt/schema'
5
- import _appConfig from '#build/app.config'
6
- import theme from '#build/ui/select'
7
- import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
- import { tv } from '../utils/tv'
9
- import type { AvatarProps, ChipProps, InputProps } from '../types'
10
- import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey, EmitsToProps } from '../types/utils'
11
-
12
- const appConfigSelect = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
13
-
14
- const select = tv({ extend: tv(theme), ...(appConfigSelect.ui?.select || {}) })
15
-
16
- export interface SelectItem {
17
- label?: string
18
- /**
19
- * @IconifyIcon
20
- */
21
- icon?: string
22
- avatar?: AvatarProps
23
- chip?: ChipProps
24
- /**
25
- * The item type.
26
- * @defaultValue 'item'
27
- */
28
- type?: 'label' | 'separator' | 'item'
29
- value?: string
30
- disabled?: boolean
31
- }
32
-
33
- type SelectVariants = VariantProps<typeof select>
34
-
35
- export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
36
- id?: string
37
- /** The placeholder text when the select is empty. */
38
- placeholder?: string
39
- /**
40
- * @defaultValue 'primary'
41
- */
42
- color?: SelectVariants['color']
43
- /**
44
- * @defaultValue 'outline'
45
- */
46
- variant?: SelectVariants['variant']
47
- /**
48
- * @defaultValue 'md'
49
- */
50
- size?: SelectVariants['size']
51
- /**
52
- * The icon displayed to open the menu.
53
- * @defaultValue appConfig.ui.icons.chevronDown
54
- * @IconifyIcon
55
- */
56
- trailingIcon?: string
57
- /**
58
- * The icon displayed when an item is selected.
59
- * @defaultValue appConfig.ui.icons.check
60
- * @IconifyIcon
61
- */
62
- selectedIcon?: string
63
- /**
64
- * The content of the menu.
65
- * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
66
- */
67
- content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>
68
- /**
69
- * Display an arrow alongside the menu.
70
- * @defaultValue false
71
- */
72
- arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>
73
- /**
74
- * Render the menu in a portal.
75
- * @defaultValue true
76
- */
77
- portal?: boolean
78
- /**
79
- * When `items` is an array of objects, select the field to use as the value.
80
- * @defaultValue 'value'
81
- */
82
- valueKey?: V
83
- /**
84
- * When `items` is an array of objects, select the field to use as the label.
85
- * @defaultValue 'label'
86
- */
87
- labelKey?: V
88
- items?: I
89
- /** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
90
- defaultValue?: SelectModelValue<T, V, M, T extends { value: infer U } ? U : never>
91
- /** The controlled value of the Select. Can be bind as `v-model`. */
92
- modelValue?: SelectModelValue<T, V, M, T extends { value: infer U } ? U : never>
93
- /** Whether multiple options can be selected or not. */
94
- multiple?: M & boolean
95
- /** Highlight the ring color like a focus state. */
96
- highlight?: boolean
97
- class?: any
98
- ui?: PartialString<typeof select.slots>
99
- }
100
-
101
- export type SelectEmits<T, V, M extends boolean> = Omit<SelectRootEmits<T>, 'update:modelValue'> & {
102
- change: [payload: Event]
103
- blur: [payload: FocusEvent]
104
- focus: [payload: FocusEvent]
105
- } & SelectModelValueEmits<T, V, M, T extends { value: infer U } ? U : never>
106
-
107
- type SlotProps<T> = (props: { item: T, index: number }) => any
108
-
109
- export interface SelectSlots<T, M extends boolean> {
110
- 'leading'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, ui: any }): any
111
- 'default'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean }): any
112
- 'trailing'(props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, ui: any }): any
113
- 'item': SlotProps<T>
114
- 'item-leading': SlotProps<T>
115
- 'item-label': SlotProps<T>
116
- 'item-trailing': SlotProps<T>
117
- }
1
+ <script>
2
+ import theme from "#build/ui/select";
118
3
  </script>
119
4
 
120
- <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
121
- import { computed, toRef } from 'vue'
122
- import { SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from 'reka-ui'
123
- import { defu } from 'defu'
124
- import { reactivePick } from '@vueuse/core'
125
- import { useAppConfig } from '#imports'
126
- import { useButtonGroup } from '../composables/useButtonGroup'
127
- import { useComponentIcons } from '../composables/useComponentIcons'
128
- import { useFormField } from '../composables/useFormField'
129
- import { get, compare } from '../utils'
130
- import UIcon from './Icon.vue'
131
- import UAvatar from './Avatar.vue'
132
- import UChip from './Chip.vue'
133
-
134
- defineOptions({ inheritAttrs: false })
135
-
136
- const props = withDefaults(defineProps<SelectProps<T, I, V, M>>(), {
137
- valueKey: 'value' as never,
138
- labelKey: 'label' as never,
139
- portal: true
140
- })
141
- const emits = defineEmits<SelectEmits<T, V, M>>()
142
- const slots = defineSlots<SelectSlots<T, M>>()
143
-
144
- const appConfig = useAppConfig()
145
- const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required', 'multiple'), emits)
146
- const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as SelectContentProps)
147
- const arrowProps = toRef(() => props.arrow as SelectArrowProps)
148
-
149
- const { emitFormChange, emitFormInput, emitFormBlur, emitFormFocus, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField<InputProps>(props)
150
- const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
151
- const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
152
-
153
- const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
154
-
155
- const ui = computed(() => select({
5
+ <script setup>
6
+ import { computed, toRef } from "vue";
7
+ import { SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from "reka-ui";
8
+ import { defu } from "defu";
9
+ import { reactivePick } from "@vueuse/core";
10
+ import { useAppConfig } from "#imports";
11
+ import { useButtonGroup } from "../composables/useButtonGroup";
12
+ import { useComponentIcons } from "../composables/useComponentIcons";
13
+ import { useFormField } from "../composables/useFormField";
14
+ import { usePortal } from "../composables/usePortal";
15
+ import { compare, get, isArrayOfArray } from "../utils";
16
+ import { tv } from "../utils/tv";
17
+ import UIcon from "./Icon.vue";
18
+ import UAvatar from "./Avatar.vue";
19
+ import UChip from "./Chip.vue";
20
+ defineOptions({ inheritAttrs: false });
21
+ const props = defineProps({
22
+ id: { type: String, required: false },
23
+ placeholder: { type: String, required: false },
24
+ color: { type: null, required: false },
25
+ variant: { type: null, required: false },
26
+ size: { type: null, required: false },
27
+ trailingIcon: { type: String, required: false },
28
+ selectedIcon: { type: String, required: false },
29
+ content: { type: Object, required: false },
30
+ arrow: { type: [Boolean, Object], required: false },
31
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
32
+ valueKey: { type: null, required: false, default: "value" },
33
+ labelKey: { type: null, required: false, default: "label" },
34
+ items: { type: null, required: false },
35
+ defaultValue: { type: null, required: false },
36
+ modelValue: { type: null, required: false },
37
+ multiple: { type: Boolean, required: false },
38
+ highlight: { type: Boolean, required: false },
39
+ class: { type: null, required: false },
40
+ ui: { type: null, required: false },
41
+ open: { type: Boolean, required: false },
42
+ defaultOpen: { type: Boolean, required: false },
43
+ autocomplete: { type: String, required: false },
44
+ disabled: { type: Boolean, required: false },
45
+ name: { type: String, required: false },
46
+ required: { type: Boolean, required: false },
47
+ icon: { type: String, required: false },
48
+ avatar: { type: Object, required: false },
49
+ leading: { type: Boolean, required: false },
50
+ leadingIcon: { type: String, required: false },
51
+ trailing: { type: Boolean, required: false },
52
+ loading: { type: Boolean, required: false },
53
+ loadingIcon: { type: String, required: false }
54
+ });
55
+ const emits = defineEmits(["update:open", "change", "blur", "focus", "update:modelValue"]);
56
+ const slots = defineSlots();
57
+ const appConfig = useAppConfig();
58
+ const rootProps = useForwardPropsEmits(reactivePick(props, "open", "defaultOpen", "disabled", "autocomplete", "required", "multiple"), emits);
59
+ const portalProps = usePortal(toRef(() => props.portal));
60
+ const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
61
+ const arrowProps = toRef(() => props.arrow);
62
+ const { emitFormChange, emitFormInput, emitFormBlur, emitFormFocus, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props);
63
+ const { orientation, size: buttonGroupSize } = useButtonGroup(props);
64
+ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })));
65
+ const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value);
66
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.select || {} })({
156
67
  color: color.value,
157
68
  variant: props.variant,
158
69
  size: selectSize?.value,
@@ -161,43 +72,40 @@ const ui = computed(() => select({
161
72
  leading: isLeading.value || !!props.avatar || !!slots.leading,
162
73
  trailing: isTrailing.value || !!slots.trailing,
163
74
  buttonGroup: orientation.value
164
- }))
165
-
166
- const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as SelectItem[][] : [])
167
- // eslint-disable-next-line vue/no-dupe-keys
168
- const items = computed(() => groups.value.flatMap(group => group) as T[])
169
-
170
- function displayValue(value?: AcceptableValue | AcceptableValue[]): string | undefined {
75
+ }));
76
+ const groups = computed(
77
+ () => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
78
+ );
79
+ const items = computed(() => groups.value.flatMap((group) => group));
80
+ function displayValue(value) {
171
81
  if (props.multiple && Array.isArray(value)) {
172
- return value.map(v => displayValue(v)).filter(Boolean).join(', ')
82
+ return value.map((v) => displayValue(v)).filter(Boolean).join(", ");
173
83
  }
174
-
175
- const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
176
- return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
84
+ const item = items.value.find((item2) => compare(typeof item2 === "object" ? get(item2, props.valueKey) : item2, value));
85
+ return item && (typeof item === "object" ? get(item, props.labelKey) : item);
177
86
  }
178
-
179
- function onUpdate(value: any) {
180
- // @ts-expect-error - 'target' does not exist in type 'EventInit'
181
- const event = new Event('change', { target: { value } })
182
- emits('change', event)
183
-
184
- emitFormChange()
185
- emitFormInput()
87
+ function onUpdate(value) {
88
+ const event = new Event("change", { target: { value } });
89
+ emits("change", event);
90
+ emitFormChange();
91
+ emitFormInput();
186
92
  }
187
- function onUpdateOpen(value: boolean) {
93
+ function onUpdateOpen(value) {
188
94
  if (!value) {
189
- const event = new FocusEvent('blur')
190
- emits('blur', event)
191
- emitFormBlur()
95
+ const event = new FocusEvent("blur");
96
+ emits("blur", event);
97
+ emitFormBlur();
192
98
  } else {
193
- const event = new FocusEvent('focus')
194
- emits('focus', event)
195
- emitFormFocus()
99
+ const event = new FocusEvent("focus");
100
+ emits("focus", event);
101
+ emitFormFocus();
196
102
  }
197
103
  }
104
+ function isSelectItem(item) {
105
+ return typeof item === "object" && item !== null;
106
+ }
198
107
  </script>
199
108
 
200
- <!-- eslint-disable vue/no-template-shadow -->
201
109
  <template>
202
110
  <SelectRoot
203
111
  v-slot="{ modelValue, open }"
@@ -205,61 +113,64 @@ function onUpdateOpen(value: boolean) {
205
113
  v-bind="rootProps"
206
114
  :autocomplete="autocomplete"
207
115
  :disabled="disabled"
208
- :default-value="(defaultValue as (AcceptableValue | AcceptableValue[] | undefined))"
209
- :model-value="(modelValue as (AcceptableValue | AcceptableValue[] | undefined))"
116
+ :default-value="defaultValue"
117
+ :model-value="modelValue"
210
118
  @update:model-value="onUpdate"
211
119
  @update:open="onUpdateOpen"
212
120
  >
213
121
  <SelectTrigger :id="id" :class="ui.base({ class: [props.class, props.ui?.base] })" v-bind="{ ...$attrs, ...ariaAttrs }">
214
122
  <span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
215
- <slot name="leading" :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open" :ui="ui">
123
+ <slot name="leading" :model-value="modelValue" :open="open" :ui="ui">
216
124
  <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
217
- <UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
125
+ <UAvatar v-else-if="!!avatar" :size="props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
218
126
  </slot>
219
127
  </span>
220
128
 
221
- <slot :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open">
129
+ <slot :model-value="modelValue" :open="open">
222
130
  <template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
223
131
  <span v-if="displayedModelValue" :class="ui.value({ class: props.ui?.value })">
224
132
  {{ displayedModelValue }}
225
133
  </span>
226
134
  <span v-else :class="ui.placeholder({ class: props.ui?.placeholder })">
227
- {{ placeholder ?? '&nbsp;' }}
135
+ {{ placeholder ?? '\xA0' }}
228
136
  </span>
229
137
  </template>
230
138
  </slot>
231
139
 
232
140
  <span v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
233
- <slot name="trailing" :model-value="(modelValue as M extends true ? AcceptableValue[] : AcceptableValue)" :open="open" :ui="ui">
141
+ <slot name="trailing" :model-value="modelValue" :open="open" :ui="ui">
234
142
  <UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
235
143
  </slot>
236
144
  </span>
237
145
  </SelectTrigger>
238
146
 
239
- <SelectPortal :disabled="!portal">
147
+ <SelectPortal v-bind="portalProps">
240
148
  <SelectContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
149
+ <slot name="content-top" />
150
+
241
151
  <SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
242
152
  <SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
243
153
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
244
- <SelectLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
245
- {{ get(item, props.labelKey as string) }}
154
+ <SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
155
+ {{ get(item, props.labelKey) }}
246
156
  </SelectLabel>
247
157
 
248
- <SelectSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
158
+ <SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
249
159
 
250
160
  <SelectItem
251
161
  v-else
252
162
  :class="ui.item({ class: props.ui?.item })"
253
- :disabled="item.disabled"
254
- :value="typeof item === 'object' ? get(item, props.valueKey as string) : item"
163
+ :disabled="isSelectItem(item) && item.disabled"
164
+ :value="isSelectItem(item) ? get(item, props.valueKey) : item"
165
+ @select="isSelectItem(item) && item.onSelect?.($event)"
255
166
  >
256
- <slot name="item" :item="(item as T)" :index="index">
257
- <slot name="item-leading" :item="(item as T)" :index="index">
258
- <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
259
- <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 })" />
167
+ <slot name="item" :item="item" :index="index">
168
+ <slot name="item-leading" :item="item" :index="index">
169
+ <UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
170
+ <UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
260
171
  <UChip
261
- v-else-if="item.chip"
262
- :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
172
+ v-else-if="isSelectItem(item) && item.chip"
173
+ :size="props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()"
263
174
  inset
264
175
  standalone
265
176
  v-bind="item.chip"
@@ -268,13 +179,13 @@ function onUpdateOpen(value: boolean) {
268
179
  </slot>
269
180
 
270
181
  <SelectItemText :class="ui.itemLabel({ class: props.ui?.itemLabel })">
271
- <slot name="item-label" :item="(item as T)" :index="index">
272
- {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
182
+ <slot name="item-label" :item="item" :index="index">
183
+ {{ isSelectItem(item) ? get(item, props.labelKey) : item }}
273
184
  </slot>
274
185
  </SelectItemText>
275
186
 
276
187
  <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
277
- <slot name="item-trailing" :item="(item as T)" :index="index" />
188
+ <slot name="item-trailing" :item="item" :index="index" />
278
189
 
279
190
  <SelectItemIndicator as-child>
280
191
  <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
@@ -286,6 +197,8 @@ function onUpdateOpen(value: boolean) {
286
197
  </SelectGroup>
287
198
  </SelectViewport>
288
199
 
200
+ <slot name="content-bottom" />
201
+
289
202
  <SelectArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
290
203
  </SelectContent>
291
204
  </SelectPortal>
@@ -0,0 +1,139 @@
1
+ import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps } from 'reka-ui';
2
+ import type { AppConfig } from '@nuxt/schema';
3
+ import theme from '#build/ui/select';
4
+ import type { UseComponentIconsProps } from '../composables/useComponentIcons';
5
+ import type { AvatarProps, ChipProps } from '../types';
6
+ import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils';
7
+ type Select = ComponentConfig<typeof theme, AppConfig, 'select'>;
8
+ interface SelectItemBase {
9
+ label?: string;
10
+ /**
11
+ * @IconifyIcon
12
+ */
13
+ icon?: string;
14
+ avatar?: AvatarProps;
15
+ chip?: ChipProps;
16
+ /**
17
+ * The item type.
18
+ * @defaultValue 'item'
19
+ */
20
+ type?: 'label' | 'separator' | 'item';
21
+ value?: string | number;
22
+ disabled?: boolean;
23
+ onSelect?(e?: Event): void;
24
+ [key: string]: any;
25
+ }
26
+ export type SelectItem = SelectItemBase | AcceptableValue | boolean;
27
+ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
28
+ id?: string;
29
+ /** The placeholder text when the select is empty. */
30
+ placeholder?: string;
31
+ /**
32
+ * @defaultValue 'primary'
33
+ */
34
+ color?: Select['variants']['color'];
35
+ /**
36
+ * @defaultValue 'outline'
37
+ */
38
+ variant?: Select['variants']['variant'];
39
+ /**
40
+ * @defaultValue 'md'
41
+ */
42
+ size?: Select['variants']['size'];
43
+ /**
44
+ * The icon displayed to open the menu.
45
+ * @defaultValue appConfig.ui.icons.chevronDown
46
+ * @IconifyIcon
47
+ */
48
+ trailingIcon?: string;
49
+ /**
50
+ * The icon displayed when an item is selected.
51
+ * @defaultValue appConfig.ui.icons.check
52
+ * @IconifyIcon
53
+ */
54
+ selectedIcon?: string;
55
+ /**
56
+ * The content of the menu.
57
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
58
+ */
59
+ content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>;
60
+ /**
61
+ * Display an arrow alongside the menu.
62
+ * @defaultValue false
63
+ */
64
+ arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>;
65
+ /**
66
+ * Render the menu in a portal.
67
+ * @defaultValue true
68
+ */
69
+ portal?: boolean | string | HTMLElement;
70
+ /**
71
+ * When `items` is an array of objects, select the field to use as the value.
72
+ * @defaultValue 'value'
73
+ */
74
+ valueKey?: VK;
75
+ /**
76
+ * When `items` is an array of objects, select the field to use as the label.
77
+ * @defaultValue 'label'
78
+ */
79
+ labelKey?: keyof NestedItem<T>;
80
+ items?: T;
81
+ /** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
82
+ defaultValue?: GetModelValue<T, VK, M>;
83
+ /** The controlled value of the Select. Can be bind as `v-model`. */
84
+ modelValue?: GetModelValue<T, VK, M>;
85
+ /** Whether multiple options can be selected or not. */
86
+ multiple?: M & boolean;
87
+ /** Highlight the ring color like a focus state. */
88
+ highlight?: boolean;
89
+ class?: any;
90
+ ui?: Select['slots'];
91
+ }
92
+ export type SelectEmits<A extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
93
+ change: [payload: Event];
94
+ blur: [payload: FocusEvent];
95
+ focus: [payload: FocusEvent];
96
+ } & GetModelValueEmits<A, VK, M>;
97
+ type SlotProps<T extends SelectItem> = (props: {
98
+ item: T;
99
+ index: number;
100
+ }) => any;
101
+ export interface SelectSlots<A extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined = undefined, M extends boolean = false, T extends NestedItem<A> = NestedItem<A>> {
102
+ 'leading'(props: {
103
+ modelValue?: GetModelValue<A, VK, M>;
104
+ open: boolean;
105
+ ui: {
106
+ [K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string;
107
+ };
108
+ }): any;
109
+ 'default'(props: {
110
+ modelValue?: GetModelValue<A, VK, M>;
111
+ open: boolean;
112
+ }): any;
113
+ 'trailing'(props: {
114
+ modelValue?: GetModelValue<A, VK, M>;
115
+ open: boolean;
116
+ ui: {
117
+ [K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string;
118
+ };
119
+ }): any;
120
+ 'item': SlotProps<T>;
121
+ 'item-leading': SlotProps<T>;
122
+ 'item-label': SlotProps<T>;
123
+ 'item-trailing': SlotProps<T>;
124
+ 'content-top': (props?: {}) => any;
125
+ 'content-bottom': (props?: {}) => any;
126
+ }
127
+ declare const _default: <T extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = "value", M extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
128
+ props: __VLS_PrettifyLocal<any & SelectProps<T, VK, M> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
129
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
130
+ attrs: any;
131
+ slots: Readonly<SelectSlots<T, VK, M, NestedItem<T>>> & SelectSlots<T, VK, M, NestedItem<T>>;
132
+ emit: ((evt: "blur", payload: FocusEvent) => void) & ((evt: "change", payload: Event) => void) & ((evt: "focus", payload: FocusEvent) => void) & ((evt: "update:open", value: boolean) => void) & ((evt: "update:modelValue", payload: GetModelValue<T, VK, M>) => void);
133
+ }>) => import("vue").VNode & {
134
+ __ctx?: Awaited<typeof __VLS_setup>;
135
+ };
136
+ export default _default;
137
+ type __VLS_PrettifyLocal<T> = {
138
+ [K in keyof T]: T[K];
139
+ } & {};