Skip to content

Commit ded0e69

Browse files
committed
fix: better checking for when a slot is empty
refactor: organize components script setup's refactor: standardize to classes -> computedClasses to not confuse with potential props refactor: standardize to attrs -> computedAttrs to not confuse with useAttrs fix(BRow): rowClasses are computed... Unsure if this was an accident before or my mistake now refactor: use props over $props when possible refactor(BFormRadioGroup): remove fragment around element fix(BListGroupItem): stop giving a TS breaking null attr and use undefined instead
1 parent c038674 commit ded0e69

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+892
-807
lines changed

packages/bootstrap-vue-3/src/components/BAccordion/BAccordion.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div :id="computedId" class="accordion" :class="classes">
2+
<div :id="computedId" class="accordion" :class="computedClasses">
33
<slot />
44
</div>
55
</template>
@@ -27,12 +27,12 @@ const computedId = useId(toRef(props, 'id'), 'accordion')
2727
const flushBoolean = useBooleanish(toRef(props, 'flush'))
2828
const freeBoolean = useBooleanish(toRef(props, 'free'))
2929
30-
const classes = computed(() => ({
30+
const computedClasses = computed(() => ({
3131
'accordion-flush': flushBoolean.value,
3232
}))
3333
3434
if (!freeBoolean.value) {
35-
provide(injectionKey, computedId.value.toString())
35+
provide(injectionKey, computedId.value)
3636
}
3737
</script>
3838

packages/bootstrap-vue-3/src/components/BAccordion/BAccordionItem.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ interface BAccordionItemProps {
4545
4646
const props = withDefaults(defineProps<BAccordionItemProps>(), {visible: false})
4747
48-
const visibleBoolean = useBooleanish(toRef(props, 'visible'))
48+
const parent = inject<string>(injectionKey, '')
4949
5050
const computedId = useId(toRef(props, 'id'), 'accordion_item')
51-
const parent = inject(injectionKey, '')
51+
52+
const visibleBoolean = useBooleanish(toRef(props, 'visible'))
5253
</script>

packages/bootstrap-vue-3/src/components/BAlert.vue

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<template>
2-
<div v-if="isAlertVisible" ref="element" class="alert" role="alert" :class="classes">
2+
<div v-if="isAlertVisible" ref="element" class="alert" role="alert" :class="computedClasses">
33
<slot />
44
<template v-if="dismissibleBoolean">
5-
<button v-if="$slots.close" type="button" data-bs-dismiss="alert" @click="closeClicked">
5+
<button v-if="hasCloseSlot" type="button" data-bs-dismiss="alert" @click="closeClicked">
66
<slot name="close" />
77
</button>
88
<b-close-button
@@ -18,9 +18,9 @@
1818
<script setup lang="ts">
1919
// import type {BAlertEmits, BAlertProps} from '../types/components'
2020
import type {Booleanish, ColorVariant} from '../types'
21-
import {computed, onBeforeUnmount, ref, toRef, watch} from 'vue'
21+
import {computed, onBeforeUnmount, ref, toRef, useSlots, watch} from 'vue'
2222
import {Alert} from 'bootstrap'
23-
import {toInteger} from '../utils'
23+
import {isEmptySlot, toInteger} from '../utils'
2424
import {useBooleanish} from '../composables'
2525
import BCloseButton from './BButton/BCloseButton.vue'
2626
@@ -56,19 +56,28 @@ interface BAlertEmits {
5656
5757
const emit = defineEmits<BAlertEmits>()
5858
59+
const slots = useSlots()
60+
61+
let _countDownTimeout: undefined | ReturnType<typeof setTimeout>
62+
5963
const element = ref<HTMLElement | null>(null)
6064
const instance = ref<Alert>()
61-
const classes = computed(() => ({
62-
[`alert-${props.variant}`]: !!props.variant,
63-
'show': !!props.modelValue,
64-
'alert-dismissible': dismissibleBoolean.value,
65-
// TODO it seems like fade is probably used here
66-
// It seems like the issue with trying to set fade is that when using transitions,
67-
// The element is null when it's trying to set the transition
68-
'fade': !!props.modelValue,
69-
}))
7065
71-
let _countDownTimeout: undefined | ReturnType<typeof setTimeout>
66+
const hasCloseSlot = computed<boolean>(() => !isEmptySlot(slots.close))
67+
68+
const isAlertVisible = computed<boolean>(() => !!props.modelValue || showBoolean.value)
69+
70+
const computedClasses = computed(() => [
71+
[`alert-${props.variant}`],
72+
{
73+
'show': !!props.modelValue,
74+
'alert-dismissible': dismissibleBoolean.value,
75+
// TODO it seems like fade is probably used here
76+
// It seems like the issue with trying to set fade is that when using transitions,
77+
// The element is null when it's trying to set the transition
78+
'fade': !!props.modelValue,
79+
},
80+
])
7281
7382
const parseCountDown = (value: boolean | number): number => {
7483
if (typeof value === 'boolean') {
@@ -79,20 +88,7 @@ const parseCountDown = (value: boolean | number): number => {
7988
return numberValue > 0 ? numberValue : 0
8089
}
8190
82-
const clearCountDownInterval = (): void => {
83-
if (_countDownTimeout === undefined) return
84-
clearTimeout(_countDownTimeout)
85-
_countDownTimeout = undefined
86-
}
87-
8891
const countDown = ref<number>(parseCountDown(props.modelValue))
89-
const isAlertVisible = computed<boolean>(() => !!props.modelValue || showBoolean.value)
90-
91-
onBeforeUnmount((): void => {
92-
clearCountDownInterval()
93-
instance.value?.dispose()
94-
instance.value = undefined
95-
})
9692
9793
const parsedModelValue = computed<boolean>(() => {
9894
if (props.modelValue === true) {
@@ -107,6 +103,12 @@ const parsedModelValue = computed<boolean>(() => {
107103
return !!props.modelValue
108104
})
109105
106+
const clearCountDownInterval = (): void => {
107+
if (_countDownTimeout === undefined) return
108+
clearTimeout(_countDownTimeout)
109+
_countDownTimeout = undefined
110+
}
111+
110112
const handleShowAndModelChanged = (): void => {
111113
countDown.value = parseCountDown(props.modelValue)
112114
if ((parsedModelValue.value || showBoolean.value) && !instance.value)
@@ -138,4 +140,10 @@ watch(countDown, (newValue) => {
138140
}, 1000)
139141
}
140142
})
143+
144+
onBeforeUnmount((): void => {
145+
clearCountDownInterval()
146+
instance.value?.dispose()
147+
instance.value = undefined
148+
})
141149
</script>

packages/bootstrap-vue-3/src/components/BAvatar/BAvatar.vue

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
<template>
22
<component
3-
:is="tag"
3+
:is="computedTag"
44
class="b-avatar"
5-
:class="classes"
6-
:style="tagStyle"
7-
v-bind="attrs"
5+
:class="computedClasses"
6+
:style="computedStyle"
7+
v-bind="computedAttrs"
88
@click="clicked"
99
>
1010
<span v-if="hasDefaultSlot" class="b-avatar-custom">
1111
<slot />
1212
</span>
13-
<span v-else-if="src" class="b-avatar-img">
13+
<span v-else-if="!!src" class="b-avatar-img">
1414
<img :src="src" :alt="alt" @error="onImgError" />
1515
</span>
16-
<span v-else-if="text" class="b-avatar-text" :class="textClasses" :style="fontStyle">
16+
<span v-else-if="!!text" class="b-avatar-text" :class="textClasses" :style="textFontStyle">
1717
{{ text }}
1818
</span>
19-
2019
<span v-if="showBadge" class="b-avatar-badge" :class="badgeClasses" :style="badgeStyle">
2120
<slot v-if="hasBadgeSlot" name="badge" />
2221
<span v-else :class="badgeTextClasses">{{ badgeText }}</span>
@@ -31,7 +30,7 @@ import type {BAvatarGroupParentData} from '../../types/components'
3130
import {computed, inject, StyleValue, toRef, useSlots} from 'vue'
3231
import type {Booleanish, ButtonType, ColorVariant, TextColorVariant} from '../../types'
3332
import {injectionKey} from './BAvatarGroup.vue'
34-
import {useBooleanish} from '../../composables'
33+
import {eagerComputed, useBooleanish} from '../../composables'
3534
3635
interface BAvatarProps {
3736
alt?: string
@@ -62,19 +61,12 @@ const props = withDefaults(defineProps<BAvatarProps>(), {
6261
badgeVariant: 'primary',
6362
button: false,
6463
buttonType: 'button',
65-
textVariant: undefined,
6664
disabled: false,
6765
rounded: 'circle',
6866
square: false,
6967
variant: 'secondary',
7068
})
7169
72-
const badgeLeftBoolean = useBooleanish(toRef(props, 'badgeLeft'))
73-
const badgeTopBoolean = useBooleanish(toRef(props, 'badgeTop'))
74-
const buttonBoolean = useBooleanish(toRef(props, 'button'))
75-
const disabledBoolean = useBooleanish(toRef(props, 'disabled'))
76-
const squareBoolean = useBooleanish(toRef(props, 'square'))
77-
7870
interface BAvatarEmits {
7971
(e: 'click', value: MouseEvent): void
8072
(e: 'img-error', value: Event): void
@@ -84,55 +76,49 @@ const emit = defineEmits<BAvatarEmits>()
8476
8577
const slots = useSlots()
8678
79+
const parentData = inject<BAvatarGroupParentData | null>(injectionKey, null)
80+
8781
const SIZES = ['sm', null, 'lg']
8882
const FONT_SIZE_SCALE = 0.4
8983
const BADGE_FONT_SIZE_SCALE = FONT_SIZE_SCALE * 0.7
9084
91-
const parentData = inject<BAvatarGroupParentData | null>(injectionKey, null)
92-
93-
const computeContrastVariant = (colorVariant: ColorVariant): ColorVariant => {
94-
const variant = colorVariant
95-
96-
if (variant === 'light') return 'dark'
97-
if (variant === 'warning') return 'dark'
98-
return 'light'
99-
}
85+
const badgeLeftBoolean = useBooleanish(toRef(props, 'badgeLeft'))
86+
const badgeTopBoolean = useBooleanish(toRef(props, 'badgeTop'))
87+
const buttonBoolean = useBooleanish(toRef(props, 'button'))
88+
const disabledBoolean = useBooleanish(toRef(props, 'disabled'))
89+
const squareBoolean = useBooleanish(toRef(props, 'square'))
10090
10191
const hasDefaultSlot = computed<boolean>(() => !isEmptySlot(slots.default))
92+
10293
const hasBadgeSlot = computed<boolean>(() => !isEmptySlot(slots.badge))
103-
const showBadge = computed<string | boolean>(
104-
() => props.badge || props.badge === '' || hasBadgeSlot.value
105-
)
10694
107-
const computedSize = computed<string | null>(() =>
95+
const showBadge = computed<boolean>(() => !!props.badge || props.badge === '' || hasBadgeSlot.value)
96+
97+
const computedSize = eagerComputed<string | null>(() =>
10898
parentData?.size ? parentData.size : computeSize(props.size)
10999
)
110100
111-
const computedVariant = computed<ColorVariant>(() =>
101+
const computedVariant = eagerComputed<ColorVariant>(() =>
112102
parentData?.variant ? parentData.variant : props.variant
113103
)
114104
115-
const computedRounded = computed<string | boolean>(() =>
105+
const computedRounded = eagerComputed<string | boolean>(() =>
116106
parentData?.rounded ? parentData.rounded : props.rounded
117107
)
118108
119-
const attrs = computed(() => ({
109+
const computedAttrs = computed(() => ({
120110
'type': buttonBoolean.value ? props.buttonType : undefined,
121111
'aria-label': props.ariaLabel || null,
122112
'disabled': disabledBoolean.value || null,
123113
}))
124114
125-
const badgeClasses = computed(() => ({
126-
[`bg-${props.badgeVariant}`]: !!props.badgeVariant,
127-
}))
115+
const badgeClasses = computed(() => [`bg-${props.badgeVariant}`])
128116
129117
const badgeText = computed<string | false>(() => (props.badge === true ? '' : props.badge))
130-
const badgeTextClasses = computed<string>(() => {
131-
const textVariant = computeContrastVariant(props.badgeVariant)
132-
return `text-${textVariant}`
133-
})
134118
135-
const classes = computed(() => ({
119+
const badgeTextClasses = computed(() => [[`text-${computeContrastVariant(props.badgeVariant)}`]])
120+
121+
const computedClasses = computed(() => ({
136122
[`b-avatar-${props.size}`]: !!props.size && SIZES.indexOf(computeSize(props.size)) !== -1,
137123
[`bg-${computedVariant.value}`]: !!computedVariant.value,
138124
[`badge`]: !buttonBoolean.value && computedVariant.value && hasDefaultSlot.value,
@@ -149,10 +135,9 @@ const classes = computed(() => ({
149135
[`btn-${computedVariant.value}`]: buttonBoolean.value ? !!computedVariant.value : false,
150136
}))
151137
152-
const textClasses = computed<string>(() => {
153-
const textVariant = props.textVariant || computeContrastVariant(computedVariant.value)
154-
return `text-${textVariant}`
155-
})
138+
const textClasses = computed(() => [
139+
[`text-${props.textVariant || computeContrastVariant(computedVariant.value)}`],
140+
])
156141
157142
const badgeStyle = computed<StyleValue>(() => {
158143
const offset = props.badgeOffset || '0px'
@@ -169,7 +154,7 @@ const badgeStyle = computed<StyleValue>(() => {
169154
}
170155
})
171156
172-
const fontStyle = computed<StyleValue>(() => {
157+
const textFontStyle = computed<StyleValue>(() => {
173158
const fontSize =
174159
SIZES.indexOf(computedSize.value || null) === -1
175160
? `calc(${computedSize.value} * ${FONT_SIZE_SCALE})`
@@ -185,16 +170,21 @@ const marginStyle = computed(() => {
185170
return value ? {marginLeft: value, marginRight: value} : {}
186171
})
187172
188-
const tag = computed<'button' | 'span'>(() => (buttonBoolean.value ? 'button' : 'span'))
189-
const tagStyle = computed(() => ({
173+
const computedTag = computed<'button' | 'span'>(() => (buttonBoolean.value ? 'button' : 'span'))
174+
175+
const computedStyle = computed(() => ({
190176
...marginStyle.value,
191177
width: computedSize.value,
192178
height: computedSize.value,
193179
}))
194180
181+
const computeContrastVariant = (colorVariant: ColorVariant): 'dark' | 'light' =>
182+
colorVariant === 'light' || colorVariant === 'warning' ? 'dark' : 'light'
183+
195184
const clicked = (e: MouseEvent): void => {
196185
if (!disabledBoolean.value && buttonBoolean.value) emit('click', e)
197186
}
187+
198188
const onImgError = (e: Event): void => emit('img-error', e)
199189
</script>
200190

packages/bootstrap-vue-3/src/components/BAvatar/BAvatarGroup.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ const squareBoolean = useBooleanish(toRef(props, 'square'))
3535
3636
const computedSize = computed<string | null>(() => computeSize(props.size))
3737
38-
const computeOverlap = (value: any): number =>
39-
typeof value === 'string' && isNumeric(value) ? toFloat(value, 0) : value || 0
40-
4138
const overlapScale = computed<number>(
4239
() => Math.min(Math.max(computeOverlap(props.overlap), 0), 1) / 2
4340
)
@@ -47,6 +44,9 @@ const paddingStyle = computed<StyleValue>(() => {
4744
return value ? {paddingLeft: value, paddingRight: value} : {}
4845
})
4946
47+
const computeOverlap = (value: any): number =>
48+
typeof value === 'string' && isNumeric(value) ? toFloat(value, 0) : value || 0
49+
5050
provide<BAvatarGroupParentData>(injectionKey, {
5151
overlapScale,
5252
size: props.size,

0 commit comments

Comments
 (0)