24
24
</template >
25
25
26
26
<script setup lang="ts">
27
- import {avatarGroupInjectionKey , isEmptySlot , isNumeric , toFloat } from ' ../../utils'
27
+ import {
28
+ avatarGroupInjectionKey ,
29
+ isEmptySlot ,
30
+ isLink ,
31
+ isNumeric ,
32
+ pluckProps ,
33
+ toFloat ,
34
+ } from ' ../../utils'
28
35
import {computed , type CSSProperties , inject , type StyleValue , useSlots } from ' vue'
29
36
import type {Booleanish , ButtonType , ColorVariant , Size , TextColorVariant } from ' ../../types'
30
37
import {useBooleanish } from ' ../../composables'
38
+ import BLink from ' ../BLink/BLink.vue'
39
+ import type {BLinkProps } from ' ../../types/BLinkProps'
31
40
32
41
const props = withDefaults (
33
- defineProps <{
34
- alt? : string
35
- ariaLabel? : string
36
- badge? : boolean | string
37
- badgeLeft? : Booleanish
38
- badgeOffset? : string
39
- badgeTop? : Booleanish
40
- badgeVariant? : ColorVariant | null
41
- button? : Booleanish
42
- buttonType? : ButtonType
43
- disabled? : Booleanish
44
- icon? : string
45
- rounded? : boolean | string
46
- size? : Size | string // TODO number --> compat
47
- square? : Booleanish
48
- src? : string
49
- text? : string
50
- textVariant? : TextColorVariant | null
51
- variant? : ColorVariant | null
52
- }>(),
42
+ defineProps <
43
+ {
44
+ alt?: string
45
+ ariaLabel ?: string
46
+ badge ?: boolean | string
47
+ badgeLeft ?: Booleanish
48
+ badgeOffset ?: string
49
+ badgeTop ?: Booleanish
50
+ badgeVariant ?: ColorVariant | null
51
+ button ?: Booleanish
52
+ buttonType ?: ButtonType
53
+ disabled ?: Booleanish
54
+ icon ?: string
55
+ rounded ?: boolean | string
56
+ size ?: Size | string // TODO number --> compat
57
+ square ?: Booleanish
58
+ src ?: string
59
+ text ?: string
60
+ textVariant ?: TextColorVariant | null
61
+ variant ?: ColorVariant | null
62
+ } & Omit < BLinkProps , ' event' | ' routerTag' >
63
+ > (),
53
64
{
54
65
ariaLabel: undefined ,
55
66
badgeOffset: undefined ,
@@ -69,6 +80,25 @@ const props = withDefaults(
69
80
rounded: ' circle' ,
70
81
square: false ,
71
82
variant: ' secondary' ,
83
+ // Link props
84
+ active: undefined ,
85
+ activeClass: ' router-link-active' ,
86
+ append: false ,
87
+ href: undefined ,
88
+ // noPrefetch: {type: [Boolean, String] as PropType<Booleanish>, default: false},
89
+ // prefetch: {type: [Boolean, String] as PropType<Booleanish>, default: null},
90
+ rel: undefined ,
91
+ replace: false ,
92
+ routerComponentName: ' router-link' ,
93
+ target: ' _self' ,
94
+ to: undefined ,
95
+ opacity: undefined ,
96
+ opacityHover: undefined ,
97
+ underlineVariant: null ,
98
+ underlineOffset: undefined ,
99
+ underlineOffsetHover: undefined ,
100
+ underlineOpacity: undefined ,
101
+ underlineOpacityHover: undefined ,
72
102
}
73
103
)
74
104
@@ -103,6 +133,8 @@ const hasBadgeSlot = computed(() => !isEmptySlot(slots.badge))
103
133
104
134
const showBadge = computed <boolean >(() => !! props .badge || props .badge === ' ' || hasBadgeSlot .value )
105
135
136
+ const computedLink = computed <boolean >(() => isLink (props ))
137
+
106
138
const computedSize = computed <string | null >(
107
139
() => parentData ?.size .value ?? computeSize (props .size )
108
140
)
@@ -114,9 +146,31 @@ const computedVariant = computed<ColorVariant | null>(
114
146
const computedRounded = computed <string | boolean >(() => parentData ?.rounded .value ?? props .rounded )
115
147
116
148
const computedAttrs = computed (() => ({
117
- ' type' : buttonBoolean .value ? props .buttonType : undefined ,
149
+ ' type' : buttonBoolean .value && ! computedLink . value ? props .buttonType : undefined ,
118
150
' aria-label' : props .ariaLabel || null ,
119
151
' disabled' : disabledBoolean .value || null ,
152
+ // Link props
153
+ ... (computedLink .value
154
+ ? pluckProps (props , {
155
+ active: true ,
156
+ activeClass: true ,
157
+ append: true ,
158
+ href: true ,
159
+ rel: true ,
160
+ replace: true ,
161
+ routerComponentName: true ,
162
+ target: true ,
163
+ to: true ,
164
+ variant: true ,
165
+ opacity: true ,
166
+ opacityHover: true ,
167
+ underlineVariant: true ,
168
+ underlineOffset: true ,
169
+ underlineOffsetHover: true ,
170
+ underlineOpacity: true ,
171
+ underlineOpacityHover: true ,
172
+ } as Record <keyof Omit <BLinkProps , ' event' | ' routerTag' >, true >)
173
+ : {}),
120
174
}))
121
175
122
176
const badgeClasses = computed (() => ({
@@ -185,7 +239,9 @@ const marginStyle = computed(() => {
185
239
return value ? {marginLeft: value , marginRight: value } : {}
186
240
})
187
241
188
- const computedTag = computed <' button' | ' span' >(() => (buttonBoolean .value ? ' button' : ' span' ))
242
+ const computedTag = computed <typeof BLink | ' button' | ' span' >(() =>
243
+ computedLink .value ? BLink : buttonBoolean .value ? ' button' : ' span'
244
+ )
189
245
190
246
const computedStyle = computed <CSSProperties >(() => ({
191
247
... marginStyle .value ,
@@ -197,7 +253,7 @@ const computeContrastVariant = (colorVariant: ColorVariant): 'dark' | 'light' =>
197
253
colorVariant === ' light' || colorVariant === ' warning' ? ' dark' : ' light'
198
254
199
255
const clicked = (e : MouseEvent ): void => {
200
- if (! disabledBoolean .value && buttonBoolean .value ) emit (' click' , e )
256
+ if (! disabledBoolean .value && ( computedLink . value || buttonBoolean .value ) ) emit (' click' , e )
201
257
}
202
258
203
259
const onImgError = (e : Event ): void => emit (' img-error' , e )
0 commit comments