@nuxt/ui 3.0.0 → 3.0.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.
- package/.nuxt/ui/button.ts +36 -36
- package/.nuxt/ui/calendar.ts +1 -1
- package/.nuxt/ui/container.ts +1 -1
- package/.nuxt/ui/drawer.ts +8 -5
- package/.nuxt/ui/navigation-menu.ts +2 -2
- package/.nuxt/ui/switch.ts +1 -1
- package/.nuxt/ui/tabs.ts +1 -1
- package/.nuxt/ui.css +1 -1
- package/README.md +11 -11
- package/cli/package.json +1 -1
- package/dist/module.cjs +2 -2
- package/dist/module.d.cts +8 -7
- package/dist/module.d.mts +8 -7
- package/dist/module.d.ts +8 -7
- package/dist/module.json +2 -2
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/Accordion.vue +11 -8
- package/dist/runtime/components/Alert.vue +1 -1
- package/dist/runtime/components/App.vue +1 -1
- package/dist/runtime/components/Avatar.vue +7 -5
- package/dist/runtime/components/Breadcrumb.vue +13 -10
- package/dist/runtime/components/Button.vue +1 -1
- package/dist/runtime/components/Calendar.vue +40 -11
- package/dist/runtime/components/Carousel.vue +7 -3
- package/dist/runtime/components/ColorPicker.vue +2 -0
- package/dist/runtime/components/CommandPalette.vue +14 -11
- package/dist/runtime/components/ContextMenu.vue +31 -17
- package/dist/runtime/components/ContextMenuContent.vue +22 -15
- package/dist/runtime/components/Drawer.vue +10 -15
- package/dist/runtime/components/DropdownMenu.vue +29 -16
- package/dist/runtime/components/DropdownMenuContent.vue +22 -15
- package/dist/runtime/components/Form.vue +22 -1
- package/dist/runtime/components/FormField.vue +6 -0
- package/dist/runtime/components/InputMenu.vue +93 -55
- package/dist/runtime/components/Link.vue +3 -0
- package/dist/runtime/components/LinkBase.vue +1 -0
- package/dist/runtime/components/Modal.vue +11 -8
- package/dist/runtime/components/NavigationMenu.vue +53 -27
- package/dist/runtime/components/PinInput.vue +2 -0
- package/dist/runtime/components/Popover.vue +3 -2
- package/dist/runtime/components/RadioGroup.vue +25 -14
- package/dist/runtime/components/Select.vue +70 -43
- package/dist/runtime/components/SelectMenu.vue +84 -49
- package/dist/runtime/components/Slideover.vue +11 -8
- package/dist/runtime/components/Stepper.vue +13 -10
- package/dist/runtime/components/Table.vue +8 -3
- package/dist/runtime/components/Tabs.vue +8 -5
- package/dist/runtime/components/Toast.vue +2 -2
- package/dist/runtime/components/Tooltip.vue +3 -2
- package/dist/runtime/components/Tree.vue +48 -32
- package/dist/runtime/composables/defineLocale.js +1 -0
- package/dist/runtime/composables/useFormField.js +1 -1
- package/dist/runtime/composables/useKbd.js +1 -1
- package/dist/runtime/composables/useLocale.js +2 -2
- package/dist/runtime/composables/useOverlay.d.ts +3 -2
- package/dist/runtime/composables/useOverlay.js +1 -1
- package/dist/runtime/locale/ca.d.ts +3 -0
- package/dist/runtime/locale/ca.js +54 -0
- package/dist/runtime/locale/ckb.d.ts +3 -0
- package/dist/runtime/locale/ckb.js +55 -0
- package/dist/runtime/locale/hy.d.ts +3 -0
- package/dist/runtime/locale/hy.js +54 -0
- package/dist/runtime/locale/index.d.ts +6 -0
- package/dist/runtime/locale/index.js +6 -0
- package/dist/runtime/locale/ro.d.ts +3 -0
- package/dist/runtime/locale/ro.js +54 -0
- package/dist/runtime/locale/ur.d.ts +3 -0
- package/dist/runtime/locale/ur.js +55 -0
- package/dist/runtime/locale/uz.d.ts +3 -0
- package/dist/runtime/locale/uz.js +54 -0
- package/dist/runtime/plugins/colors.js +19 -15
- package/dist/runtime/types/form.d.ts +2 -3
- package/dist/runtime/types/index.d.ts +2 -0
- package/dist/runtime/types/index.js +2 -0
- package/dist/runtime/types/utils.d.ts +28 -8
- package/dist/runtime/utils/form.d.ts +0 -4
- package/dist/runtime/utils/form.js +2 -47
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +3 -0
- package/dist/runtime/utils/link.d.ts +2 -25
- package/dist/runtime/utils/link.js +31 -1
- package/dist/runtime/utils/tv.js +1 -1
- package/dist/runtime/vue/components/Link.vue +3 -0
- package/dist/runtime/vue/plugins/head.js +3 -0
- package/dist/runtime/vue/stubs.d.ts +7 -3
- package/dist/runtime/vue/stubs.js +12 -4
- package/dist/shared/{ui.COBs1u5H.cjs → ui.BL-XB3u1.cjs} +26 -26
- package/dist/shared/{ui.yjbGE7Dx.mjs → ui.BkNUP964.mjs} +26 -26
- package/dist/types.d.mts +7 -1
- package/dist/types.d.ts +7 -1
- package/dist/unplugin.cjs +6 -2
- package/dist/unplugin.d.cts +2 -1
- package/dist/unplugin.d.mts +2 -1
- package/dist/unplugin.d.ts +2 -1
- package/dist/unplugin.mjs +6 -2
- package/dist/vite.cjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +46 -29
|
@@ -1,20 +1,29 @@
|
|
|
1
|
+
<!-- eslint-disable vue/block-tag-newline -->
|
|
1
2
|
<script lang="ts">
|
|
2
3
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
-
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, CollapsibleRootProps } from 'reka-ui'
|
|
4
|
+
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, NavigationMenuContentEmits, CollapsibleRootProps } from 'reka-ui'
|
|
4
5
|
import type { AppConfig } from '@nuxt/schema'
|
|
5
6
|
import _appConfig from '#build/app.config'
|
|
6
7
|
import theme from '#build/ui/navigation-menu'
|
|
7
8
|
import { tv } from '../utils/tv'
|
|
8
9
|
import type { AvatarProps, BadgeProps, LinkProps } from '../types'
|
|
9
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
ArrayOrNested,
|
|
12
|
+
DynamicSlots,
|
|
13
|
+
MergeTypes,
|
|
14
|
+
NestedItem,
|
|
15
|
+
PartialString,
|
|
16
|
+
EmitsToProps
|
|
17
|
+
} from '../types/utils'
|
|
10
18
|
|
|
11
19
|
const appConfigNavigationMenu = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
|
|
12
20
|
|
|
13
21
|
const navigationMenu = tv({ extend: tv(theme), ...(appConfigNavigationMenu.ui?.navigationMenu || {}) })
|
|
14
22
|
|
|
15
|
-
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, '
|
|
23
|
+
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type'> {
|
|
16
24
|
/** Description is only used when `orientation` is `horizontal`. */
|
|
17
25
|
description?: string
|
|
26
|
+
[key: string]: any
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'>, Pick<CollapsibleRootProps, 'defaultOpen' | 'open'> {
|
|
@@ -43,11 +52,12 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
|
|
43
52
|
value?: string
|
|
44
53
|
children?: NavigationMenuChildItem[]
|
|
45
54
|
onSelect?(e: Event): void
|
|
55
|
+
[key: string]: any
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
type NavigationMenuVariants = VariantProps<typeof navigationMenu>
|
|
49
59
|
|
|
50
|
-
export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'modelValue' | 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'> {
|
|
60
|
+
export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem> = ArrayOrNested<NavigationMenuItem>> extends Pick<NavigationMenuRootProps, 'modelValue' | 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'> {
|
|
51
61
|
/**
|
|
52
62
|
* The element or component this component should render as.
|
|
53
63
|
* @defaultValue 'div'
|
|
@@ -93,7 +103,7 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'm
|
|
|
93
103
|
*/
|
|
94
104
|
highlightColor?: NavigationMenuVariants['highlightColor']
|
|
95
105
|
/** The content of the menu. */
|
|
96
|
-
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
106
|
+
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<NavigationMenuContentEmits>>
|
|
97
107
|
/**
|
|
98
108
|
* The orientation of the content.
|
|
99
109
|
* Only works when `orientation` is `horizontal`.
|
|
@@ -109,30 +119,34 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'm
|
|
|
109
119
|
* The key used to get the label from the item.
|
|
110
120
|
* @defaultValue 'label'
|
|
111
121
|
*/
|
|
112
|
-
labelKey?:
|
|
122
|
+
labelKey?: keyof NestedItem<T>
|
|
113
123
|
class?: any
|
|
114
124
|
ui?: PartialString<typeof navigationMenu.slots>
|
|
115
125
|
}
|
|
116
126
|
|
|
117
127
|
export interface NavigationMenuEmits extends NavigationMenuRootEmits {}
|
|
118
128
|
|
|
119
|
-
type SlotProps<T> = (props: { item: T, index: number, active?: boolean }) => any
|
|
129
|
+
type SlotProps<T extends NavigationMenuItem> = (props: { item: T, index: number, active?: boolean }) => any
|
|
120
130
|
|
|
121
|
-
export type NavigationMenuSlots<
|
|
131
|
+
export type NavigationMenuSlots<
|
|
132
|
+
A extends ArrayOrNested<NavigationMenuItem> = ArrayOrNested<NavigationMenuItem>,
|
|
133
|
+
T extends NestedItem<A> = NestedItem<A>
|
|
134
|
+
> = {
|
|
122
135
|
'item': SlotProps<T>
|
|
123
136
|
'item-leading': SlotProps<T>
|
|
124
137
|
'item-label': SlotProps<T>
|
|
125
138
|
'item-trailing': SlotProps<T>
|
|
126
139
|
'item-content': SlotProps<T>
|
|
127
|
-
} & DynamicSlots<T,
|
|
140
|
+
} & DynamicSlots<MergeTypes<T>, 'leading' | 'label' | 'trailing' | 'content', { index: number, active?: boolean }>
|
|
141
|
+
|
|
128
142
|
</script>
|
|
129
143
|
|
|
130
|
-
<script setup lang="ts" generic="T extends
|
|
144
|
+
<script setup lang="ts" generic="T extends ArrayOrNested<NavigationMenuItem>">
|
|
131
145
|
import { computed, toRef } from 'vue'
|
|
132
146
|
import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, useForwardPropsEmits } from 'reka-ui'
|
|
133
147
|
import { createReusableTemplate } from '@vueuse/core'
|
|
134
148
|
import { useAppConfig } from '#imports'
|
|
135
|
-
import { get } from '../utils'
|
|
149
|
+
import { get, isArrayOfArray } from '../utils'
|
|
136
150
|
import { pickLinkProps } from '../utils/link'
|
|
137
151
|
import ULinkBase from './LinkBase.vue'
|
|
138
152
|
import ULink from './Link.vue'
|
|
@@ -141,7 +155,7 @@ import UIcon from './Icon.vue'
|
|
|
141
155
|
import UBadge from './Badge.vue'
|
|
142
156
|
import UCollapsible from './Collapsible.vue'
|
|
143
157
|
|
|
144
|
-
const props = withDefaults(defineProps<NavigationMenuProps<
|
|
158
|
+
const props = withDefaults(defineProps<NavigationMenuProps<T>>(), {
|
|
145
159
|
orientation: 'horizontal',
|
|
146
160
|
contentOrientation: 'horizontal',
|
|
147
161
|
externalIcon: true,
|
|
@@ -168,8 +182,14 @@ const rootProps = useForwardPropsEmits(computed(() => ({
|
|
|
168
182
|
const contentProps = toRef(() => props.content)
|
|
169
183
|
|
|
170
184
|
const appConfig = useAppConfig()
|
|
171
|
-
const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<
|
|
172
|
-
|
|
185
|
+
const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<
|
|
186
|
+
{ item: NavigationMenuItem, index: number, active?: boolean },
|
|
187
|
+
NavigationMenuSlots<T>
|
|
188
|
+
>()
|
|
189
|
+
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<
|
|
190
|
+
{ item: NavigationMenuItem, index: number, level?: number },
|
|
191
|
+
NavigationMenuSlots<T>
|
|
192
|
+
>({
|
|
173
193
|
props: {
|
|
174
194
|
item: Object,
|
|
175
195
|
index: Number,
|
|
@@ -187,30 +207,36 @@ const ui = computed(() => navigationMenu({
|
|
|
187
207
|
highlightColor: props.highlightColor || props.color
|
|
188
208
|
}))
|
|
189
209
|
|
|
190
|
-
const lists = computed
|
|
210
|
+
const lists = computed<NavigationMenuItem[][]>(() =>
|
|
211
|
+
props.items?.length
|
|
212
|
+
? isArrayOfArray(props.items)
|
|
213
|
+
? props.items
|
|
214
|
+
: [props.items]
|
|
215
|
+
: []
|
|
216
|
+
)
|
|
191
217
|
</script>
|
|
192
218
|
|
|
193
219
|
<template>
|
|
194
220
|
<DefineLinkTemplate v-slot="{ item, active, index }">
|
|
195
|
-
<slot :name="item.slot || 'item'" :item="
|
|
196
|
-
<slot :name="item.slot ? `${item.slot}-leading` : 'item-leading'" :item="
|
|
221
|
+
<slot :name="((item.slot || 'item') as keyof NavigationMenuSlots<T>)" :item="item" :index="index">
|
|
222
|
+
<slot :name="((item.slot ? `${item.slot}-leading` : 'item-leading') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
|
197
223
|
<UAvatar v-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active, disabled: !!item.disabled })" />
|
|
198
224
|
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active, disabled: !!item.disabled })" />
|
|
199
225
|
</slot>
|
|
200
226
|
|
|
201
227
|
<span
|
|
202
|
-
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : 'item-label'])"
|
|
228
|
+
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>])"
|
|
203
229
|
:class="ui.linkLabel({ class: props.ui?.linkLabel })"
|
|
204
230
|
>
|
|
205
|
-
<slot :name="item.slot ? `${item.slot}-label` : 'item-label'" :item="
|
|
231
|
+
<slot :name="((item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
|
206
232
|
{{ get(item, props.labelKey as string) }}
|
|
207
233
|
</slot>
|
|
208
234
|
|
|
209
235
|
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
|
|
210
236
|
</span>
|
|
211
237
|
|
|
212
|
-
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing'])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
|
|
213
|
-
<slot :name="item.slot ? `${item.slot}-trailing` : 'item-trailing'" :item="
|
|
238
|
+
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[(item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
|
|
239
|
+
<slot :name="((item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
|
214
240
|
<UBadge
|
|
215
241
|
v-if="item.badge"
|
|
216
242
|
color="neutral"
|
|
@@ -220,7 +246,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
|
|
|
220
246
|
:class="ui.linkTrailingBadge({ class: props.ui?.linkTrailingBadge })"
|
|
221
247
|
/>
|
|
222
248
|
|
|
223
|
-
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
|
|
249
|
+
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
|
|
224
250
|
<UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
|
|
225
251
|
</slot>
|
|
226
252
|
</span>
|
|
@@ -237,23 +263,23 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
|
|
|
237
263
|
:open="item.open"
|
|
238
264
|
>
|
|
239
265
|
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
|
240
|
-
<ReuseLinkTemplate :item="
|
|
266
|
+
<ReuseLinkTemplate :item="item" :index="index" />
|
|
241
267
|
</div>
|
|
242
268
|
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && !collapsed) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
|
|
243
269
|
<component
|
|
244
|
-
:is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
|
|
270
|
+
:is="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) ? NavigationMenuTrigger : NavigationMenuLink"
|
|
245
271
|
as-child
|
|
246
272
|
:active="active || item.active"
|
|
247
273
|
:disabled="item.disabled"
|
|
248
274
|
@select="item.onSelect"
|
|
249
275
|
>
|
|
250
276
|
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
|
251
|
-
<ReuseLinkTemplate :item="
|
|
277
|
+
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
|
|
252
278
|
</ULinkBase>
|
|
253
279
|
</component>
|
|
254
280
|
|
|
255
|
-
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
|
|
256
|
-
<slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="
|
|
281
|
+
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
|
|
282
|
+
<slot :name="((item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
|
257
283
|
<ul :class="ui.childList({ class: props.ui?.childList })">
|
|
258
284
|
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
|
|
259
285
|
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- eslint-disable vue/block-tag-newline -->
|
|
1
2
|
<script lang="ts">
|
|
2
3
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
4
|
import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
|
|
@@ -45,6 +46,7 @@ export type PinInputEmits = PinInputRootEmits & {
|
|
|
45
46
|
change: [payload: Event]
|
|
46
47
|
blur: [payload: Event]
|
|
47
48
|
}
|
|
49
|
+
|
|
48
50
|
</script>
|
|
49
51
|
|
|
50
52
|
<script setup lang="ts">
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverArrowProps } from 'reka-ui'
|
|
2
|
+
import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverContentEmits, PopoverArrowProps } from 'reka-ui'
|
|
3
3
|
import type { AppConfig } from '@nuxt/schema'
|
|
4
4
|
import _appConfig from '#build/app.config'
|
|
5
5
|
import theme from '#build/ui/popover'
|
|
6
6
|
import { tv } from '../utils/tv'
|
|
7
|
+
import type { EmitsToProps } from '../types/utils'
|
|
7
8
|
|
|
8
9
|
const appConfigPopover = _appConfig as AppConfig & { ui: { popover: Partial<typeof theme> } }
|
|
9
10
|
|
|
@@ -19,7 +20,7 @@ export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps,
|
|
|
19
20
|
* The content of the popover.
|
|
20
21
|
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
|
21
22
|
*/
|
|
22
|
-
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
23
|
+
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<PopoverContentEmits>>
|
|
23
24
|
/**
|
|
24
25
|
* Display an arrow alongside the popover.
|
|
25
26
|
* @defaultValue false
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
-
import type { RadioGroupRootProps, RadioGroupRootEmits
|
|
3
|
+
import type { RadioGroupRootProps, RadioGroupRootEmits } 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/radio-group'
|
|
7
7
|
import { tv } from '../utils/tv'
|
|
8
|
+
import type { AcceptableValue } from '../types/utils'
|
|
8
9
|
|
|
9
10
|
const appConfigRadioGroup = _appConfig as AppConfig & { ui: { radioGroup: Partial<typeof theme> } }
|
|
10
11
|
|
|
@@ -12,14 +13,16 @@ const radioGroup = tv({ extend: tv(theme), ...(appConfigRadioGroup.ui?.radioGrou
|
|
|
12
13
|
|
|
13
14
|
type RadioGroupVariants = VariantProps<typeof radioGroup>
|
|
14
15
|
|
|
15
|
-
export
|
|
16
|
+
export type RadioGroupValue = AcceptableValue
|
|
17
|
+
export type RadioGroupItem = {
|
|
16
18
|
label?: string
|
|
17
19
|
description?: string
|
|
18
20
|
disabled?: boolean
|
|
19
21
|
value?: string
|
|
20
|
-
|
|
22
|
+
[key: string]: any
|
|
23
|
+
} | RadioGroupValue
|
|
21
24
|
|
|
22
|
-
export interface RadioGroupProps<T> extends Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
|
|
25
|
+
export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> extends Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
|
|
23
26
|
/**
|
|
24
27
|
* The element or component this component should render as.
|
|
25
28
|
* @defaultValue 'div'
|
|
@@ -63,16 +66,16 @@ export type RadioGroupEmits = RadioGroupRootEmits & {
|
|
|
63
66
|
change: [payload: Event]
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
type SlotProps<T> = (props: { item: T, modelValue?:
|
|
69
|
+
type SlotProps<T extends RadioGroupItem> = (props: { item: T & { id: string }, modelValue?: RadioGroupValue }) => any
|
|
67
70
|
|
|
68
|
-
export interface RadioGroupSlots<T> {
|
|
71
|
+
export interface RadioGroupSlots<T extends RadioGroupItem = RadioGroupItem> {
|
|
69
72
|
legend(props?: {}): any
|
|
70
73
|
label: SlotProps<T>
|
|
71
74
|
description: SlotProps<T>
|
|
72
75
|
}
|
|
73
76
|
</script>
|
|
74
77
|
|
|
75
|
-
<script setup lang="ts" generic="T extends RadioGroupItem
|
|
78
|
+
<script setup lang="ts" generic="T extends RadioGroupItem">
|
|
76
79
|
import { computed, useId } from 'vue'
|
|
77
80
|
import { RadioGroupRoot, RadioGroupItem, RadioGroupIndicator, Label, useForwardPropsEmits } from 'reka-ui'
|
|
78
81
|
import { reactivePick } from '@vueuse/core'
|
|
@@ -102,11 +105,19 @@ const ui = computed(() => radioGroup({
|
|
|
102
105
|
}))
|
|
103
106
|
|
|
104
107
|
function normalizeItem(item: any) {
|
|
105
|
-
if (
|
|
108
|
+
if (item === null) {
|
|
109
|
+
return {
|
|
110
|
+
id: `${id}:null`,
|
|
111
|
+
value: undefined,
|
|
112
|
+
label: undefined
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
106
117
|
return {
|
|
107
118
|
id: `${id}:${item}`,
|
|
108
|
-
value: item,
|
|
109
|
-
label: item
|
|
119
|
+
value: String(item),
|
|
120
|
+
label: String(item)
|
|
110
121
|
}
|
|
111
122
|
}
|
|
112
123
|
|
|
@@ -161,8 +172,8 @@ function onUpdate(value: any) {
|
|
|
161
172
|
<RadioGroupItem
|
|
162
173
|
:id="item.id"
|
|
163
174
|
:value="item.value"
|
|
164
|
-
:disabled="disabled"
|
|
165
|
-
:class="ui.base({ class: props.ui?.base })"
|
|
175
|
+
:disabled="item.disabled"
|
|
176
|
+
:class="ui.base({ class: props.ui?.base, disabled: item.disabled })"
|
|
166
177
|
>
|
|
167
178
|
<RadioGroupIndicator :class="ui.indicator({ class: props.ui?.indicator })" />
|
|
168
179
|
</RadioGroupItem>
|
|
@@ -170,10 +181,10 @@ function onUpdate(value: any) {
|
|
|
170
181
|
|
|
171
182
|
<div :class="ui.wrapper({ class: props.ui?.wrapper })">
|
|
172
183
|
<Label :class="ui.label({ class: props.ui?.label })" :for="item.id">
|
|
173
|
-
<slot name="label" :item="item" :model-value="modelValue">{{ item.label }}</slot>
|
|
184
|
+
<slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">{{ item.label }}</slot>
|
|
174
185
|
</Label>
|
|
175
186
|
<p v-if="item.description || !!slots.description" :class="ui.description({ class: props.ui?.description })">
|
|
176
|
-
<slot name="description" :item="item" :model-value="modelValue">
|
|
187
|
+
<slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
|
177
188
|
{{ item.description }}
|
|
178
189
|
</slot>
|
|
179
190
|
</p>
|
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
-
import type { SelectRootProps, SelectRootEmits, SelectContentProps,
|
|
3
|
+
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps } 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'
|
|
7
7
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
8
8
|
import { tv } from '../utils/tv'
|
|
9
9
|
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
AcceptableValue,
|
|
12
|
+
ArrayOrNested,
|
|
13
|
+
GetItemKeys,
|
|
14
|
+
GetItemValue,
|
|
15
|
+
GetModelValue,
|
|
16
|
+
GetModelValueEmits,
|
|
17
|
+
NestedItem,
|
|
18
|
+
PartialString,
|
|
19
|
+
EmitsToProps
|
|
20
|
+
} from '../types/utils'
|
|
11
21
|
|
|
12
22
|
const appConfigSelect = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
|
|
13
23
|
|
|
14
24
|
const select = tv({ extend: tv(theme), ...(appConfigSelect.ui?.select || {}) })
|
|
15
25
|
|
|
16
|
-
|
|
26
|
+
interface SelectItemBase {
|
|
17
27
|
label?: string
|
|
18
28
|
/**
|
|
19
29
|
* @IconifyIcon
|
|
@@ -26,13 +36,15 @@ export interface SelectItem {
|
|
|
26
36
|
* @defaultValue 'item'
|
|
27
37
|
*/
|
|
28
38
|
type?: 'label' | 'separator' | 'item'
|
|
29
|
-
value?: string
|
|
39
|
+
value?: string | number
|
|
30
40
|
disabled?: boolean
|
|
41
|
+
[key: string]: any
|
|
31
42
|
}
|
|
43
|
+
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
|
32
44
|
|
|
33
45
|
type SelectVariants = VariantProps<typeof select>
|
|
34
46
|
|
|
35
|
-
export interface SelectProps<T extends
|
|
47
|
+
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 {
|
|
36
48
|
id?: string
|
|
37
49
|
/** The placeholder text when the select is empty. */
|
|
38
50
|
placeholder?: string
|
|
@@ -64,7 +76,7 @@ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends Maybe
|
|
|
64
76
|
* The content of the menu.
|
|
65
77
|
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
|
66
78
|
*/
|
|
67
|
-
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
79
|
+
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>
|
|
68
80
|
/**
|
|
69
81
|
* Display an arrow alongside the menu.
|
|
70
82
|
* @defaultValue false
|
|
@@ -79,17 +91,17 @@ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends Maybe
|
|
|
79
91
|
* When `items` is an array of objects, select the field to use as the value.
|
|
80
92
|
* @defaultValue 'value'
|
|
81
93
|
*/
|
|
82
|
-
valueKey?:
|
|
94
|
+
valueKey?: VK
|
|
83
95
|
/**
|
|
84
96
|
* When `items` is an array of objects, select the field to use as the label.
|
|
85
97
|
* @defaultValue 'label'
|
|
86
98
|
*/
|
|
87
|
-
labelKey?:
|
|
88
|
-
items?:
|
|
99
|
+
labelKey?: keyof NestedItem<T>
|
|
100
|
+
items?: T
|
|
89
101
|
/** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
|
|
90
|
-
defaultValue?:
|
|
102
|
+
defaultValue?: GetModelValue<T, VK, M>
|
|
91
103
|
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
92
|
-
modelValue?:
|
|
104
|
+
modelValue?: GetModelValue<T, VK, M>
|
|
93
105
|
/** Whether multiple options can be selected or not. */
|
|
94
106
|
multiple?: M & boolean
|
|
95
107
|
/** Highlight the ring color like a focus state. */
|
|
@@ -98,18 +110,23 @@ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends Maybe
|
|
|
98
110
|
ui?: PartialString<typeof select.slots>
|
|
99
111
|
}
|
|
100
112
|
|
|
101
|
-
export type SelectEmits<
|
|
113
|
+
export type SelectEmits<A extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
|
|
102
114
|
change: [payload: Event]
|
|
103
115
|
blur: [payload: FocusEvent]
|
|
104
116
|
focus: [payload: FocusEvent]
|
|
105
|
-
} &
|
|
117
|
+
} & GetModelValueEmits<A, VK, M>
|
|
106
118
|
|
|
107
|
-
type SlotProps<T> = (props: { item: T, index: number }) => any
|
|
119
|
+
type SlotProps<T extends SelectItem> = (props: { item: T, index: number }) => any
|
|
108
120
|
|
|
109
|
-
export interface SelectSlots<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
export interface SelectSlots<
|
|
122
|
+
A extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>,
|
|
123
|
+
VK extends GetItemKeys<A> | undefined = undefined,
|
|
124
|
+
M extends boolean = false,
|
|
125
|
+
T extends NestedItem<A> = NestedItem<A>
|
|
126
|
+
> {
|
|
127
|
+
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
|
128
|
+
'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
|
|
129
|
+
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
|
113
130
|
'item': SlotProps<T>
|
|
114
131
|
'item-leading': SlotProps<T>
|
|
115
132
|
'item-label': SlotProps<T>
|
|
@@ -117,7 +134,7 @@ export interface SelectSlots<T, M extends boolean> {
|
|
|
117
134
|
}
|
|
118
135
|
</script>
|
|
119
136
|
|
|
120
|
-
<script setup lang="ts" generic="T extends
|
|
137
|
+
<script setup lang="ts" generic="T extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false">
|
|
121
138
|
import { computed, toRef } from 'vue'
|
|
122
139
|
import { SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from 'reka-ui'
|
|
123
140
|
import { defu } from 'defu'
|
|
@@ -126,20 +143,20 @@ import { useAppConfig } from '#imports'
|
|
|
126
143
|
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
127
144
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
128
145
|
import { useFormField } from '../composables/useFormField'
|
|
129
|
-
import { get,
|
|
146
|
+
import { compare, get, isArrayOfArray } from '../utils'
|
|
130
147
|
import UIcon from './Icon.vue'
|
|
131
148
|
import UAvatar from './Avatar.vue'
|
|
132
149
|
import UChip from './Chip.vue'
|
|
133
150
|
|
|
134
151
|
defineOptions({ inheritAttrs: false })
|
|
135
152
|
|
|
136
|
-
const props = withDefaults(defineProps<SelectProps<T,
|
|
153
|
+
const props = withDefaults(defineProps<SelectProps<T, VK, M>>(), {
|
|
137
154
|
valueKey: 'value' as never,
|
|
138
155
|
labelKey: 'label' as never,
|
|
139
156
|
portal: true
|
|
140
157
|
})
|
|
141
|
-
const emits = defineEmits<SelectEmits<T,
|
|
142
|
-
const slots = defineSlots<SelectSlots<T, M>>()
|
|
158
|
+
const emits = defineEmits<SelectEmits<T, VK, M>>()
|
|
159
|
+
const slots = defineSlots<SelectSlots<T, VK, M>>()
|
|
143
160
|
|
|
144
161
|
const appConfig = useAppConfig()
|
|
145
162
|
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required', 'multiple'), emits)
|
|
@@ -163,11 +180,17 @@ const ui = computed(() => select({
|
|
|
163
180
|
buttonGroup: orientation.value
|
|
164
181
|
}))
|
|
165
182
|
|
|
166
|
-
const groups = computed
|
|
183
|
+
const groups = computed<SelectItem[][]>(() =>
|
|
184
|
+
props.items?.length
|
|
185
|
+
? isArrayOfArray(props.items)
|
|
186
|
+
? props.items
|
|
187
|
+
: [props.items]
|
|
188
|
+
: []
|
|
189
|
+
)
|
|
167
190
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
168
191
|
const items = computed(() => groups.value.flatMap(group => group) as T[])
|
|
169
192
|
|
|
170
|
-
function displayValue(value?:
|
|
193
|
+
function displayValue(value?: GetItemValue<T, VK> | GetItemValue<T, VK>[]): string {
|
|
171
194
|
if (props.multiple && Array.isArray(value)) {
|
|
172
195
|
return value.map(v => displayValue(v)).filter(Boolean).join(', ')
|
|
173
196
|
}
|
|
@@ -195,6 +218,10 @@ function onUpdateOpen(value: boolean) {
|
|
|
195
218
|
emitFormFocus()
|
|
196
219
|
}
|
|
197
220
|
}
|
|
221
|
+
|
|
222
|
+
function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
223
|
+
return typeof item === 'object' && item !== null
|
|
224
|
+
}
|
|
198
225
|
</script>
|
|
199
226
|
|
|
200
227
|
<!-- eslint-disable vue/no-template-shadow -->
|
|
@@ -205,21 +232,21 @@ function onUpdateOpen(value: boolean) {
|
|
|
205
232
|
v-bind="rootProps"
|
|
206
233
|
:autocomplete="autocomplete"
|
|
207
234
|
:disabled="disabled"
|
|
208
|
-
:default-value="(defaultValue as (AcceptableValue | AcceptableValue[]
|
|
209
|
-
:model-value="(modelValue as (AcceptableValue | AcceptableValue[]
|
|
235
|
+
:default-value="(defaultValue as (AcceptableValue | AcceptableValue[]))"
|
|
236
|
+
:model-value="(modelValue as (AcceptableValue | AcceptableValue[]))"
|
|
210
237
|
@update:model-value="onUpdate"
|
|
211
238
|
@update:open="onUpdateOpen"
|
|
212
239
|
>
|
|
213
240
|
<SelectTrigger :id="id" :class="ui.base({ class: [props.class, props.ui?.base] })" v-bind="{ ...$attrs, ...ariaAttrs }">
|
|
214
241
|
<span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
|
|
215
|
-
<slot name="leading" :model-value="(modelValue as
|
|
242
|
+
<slot name="leading" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :ui="ui">
|
|
216
243
|
<UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
|
|
217
244
|
<UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
218
245
|
</slot>
|
|
219
246
|
</span>
|
|
220
247
|
|
|
221
|
-
<slot :model-value="(modelValue as
|
|
222
|
-
<template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
|
|
248
|
+
<slot :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open">
|
|
249
|
+
<template v-for="displayedModelValue in [displayValue(modelValue as GetModelValue<T, VK, M>)]" :key="displayedModelValue">
|
|
223
250
|
<span v-if="displayedModelValue" :class="ui.value({ class: props.ui?.value })">
|
|
224
251
|
{{ displayedModelValue }}
|
|
225
252
|
</span>
|
|
@@ -230,7 +257,7 @@ function onUpdateOpen(value: boolean) {
|
|
|
230
257
|
</slot>
|
|
231
258
|
|
|
232
259
|
<span v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
|
|
233
|
-
<slot name="trailing" :model-value="(modelValue as
|
|
260
|
+
<slot name="trailing" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :ui="ui">
|
|
234
261
|
<UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
|
|
235
262
|
</slot>
|
|
236
263
|
</span>
|
|
@@ -241,24 +268,24 @@ function onUpdateOpen(value: boolean) {
|
|
|
241
268
|
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
|
|
242
269
|
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
|
243
270
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
244
|
-
<SelectLabel v-if="item
|
|
271
|
+
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
|
245
272
|
{{ get(item, props.labelKey as string) }}
|
|
246
273
|
</SelectLabel>
|
|
247
274
|
|
|
248
|
-
<SelectSeparator v-else-if="item
|
|
275
|
+
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
|
249
276
|
|
|
250
277
|
<SelectItem
|
|
251
278
|
v-else
|
|
252
279
|
:class="ui.item({ class: props.ui?.item })"
|
|
253
|
-
:disabled="item.disabled"
|
|
254
|
-
:value="
|
|
280
|
+
:disabled="isSelectItem(item) && item.disabled"
|
|
281
|
+
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
|
255
282
|
>
|
|
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 })" />
|
|
283
|
+
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
|
284
|
+
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
|
285
|
+
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
|
286
|
+
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
260
287
|
<UChip
|
|
261
|
-
v-else-if="item.chip"
|
|
288
|
+
v-else-if="isSelectItem(item) && item.chip"
|
|
262
289
|
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
|
263
290
|
inset
|
|
264
291
|
standalone
|
|
@@ -268,13 +295,13 @@ function onUpdateOpen(value: boolean) {
|
|
|
268
295
|
</slot>
|
|
269
296
|
|
|
270
297
|
<SelectItemText :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
|
271
|
-
<slot name="item-label" :item="(item as T)" :index="index">
|
|
272
|
-
{{
|
|
298
|
+
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
|
299
|
+
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
|
273
300
|
</slot>
|
|
274
301
|
</SelectItemText>
|
|
275
302
|
|
|
276
303
|
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
|
277
|
-
<slot name="item-trailing" :item="(item as T)" :index="index" />
|
|
304
|
+
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
|
278
305
|
|
|
279
306
|
<SelectItemIndicator as-child>
|
|
280
307
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|