Skip to content

Commit 3a41a93

Browse files
authored
Merge pull request #738 from VividLemon/main
refactor(BOverlay): convert to template and script setup syntax
2 parents cebcc14 + b7106f4 commit 3a41a93

File tree

5 files changed

+850
-149
lines changed

5 files changed

+850
-149
lines changed
Lines changed: 142 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,151 @@
1-
<script lang="ts">
2-
import type {Booleanish, ColorVariant} from '../../types'
3-
import {normalizeSlot, toFloat} from '../../utils'
1+
<template>
2+
<component :is="wrapTag" class="b-overlay-wrap position-relative" :aria-busy="computedAriaBusy">
3+
<slot />
4+
<b-transition
5+
:no-fade="noFadeBoolean"
6+
:trans-props="{enterToClass: 'show'}"
7+
name="fade"
8+
@on-after-enter="emit('shown')"
9+
@on-after-leave="emit('hidden')"
10+
>
11+
<component
12+
:is="overlayTag"
13+
v-if="showBoolean"
14+
:class="overlayClasses"
15+
:style="overlayStyles"
16+
@click="emit('click', $event)"
17+
>
18+
<div class="position-absolute" :class="blurClasses" :style="blurStyles" />
19+
20+
<div class="position-absolute" :style="spinWrapperStyles">
21+
<slot name="overlay" v-bind="spinnerAttrs">
22+
<b-spinner v-bind="spinnerAttrs" />
23+
</slot>
24+
</div>
25+
</component>
26+
</b-transition>
27+
</component>
28+
</template>
29+
30+
<script setup lang="ts">
31+
import {computed, toRef} from 'vue'
32+
import type {Booleanish, ColorVariant, SpinnerType} from '../../types'
433
import {useBooleanish} from '../../composables'
5-
import {computed, defineComponent, h, PropType, resolveComponent, toRef} from 'vue'
634
import BTransition from '../BTransition/BTransition.vue'
35+
import BSpinner from '../BSpinner.vue'
736
8-
const POSITION_COVER = {top: 0, left: 0, bottom: 0, right: 0}
9-
const SLOT_NAME_DEFAULT = 'default'
10-
const SLOT_NAME_OVERLAY = 'overlay'
37+
interface Props {
38+
bgColor?: string
39+
blur?: string
40+
fixed?: Booleanish
41+
noCenter?: Booleanish
42+
noFade?: Booleanish
43+
noWrap?: Booleanish
44+
opacity?: number | string
45+
overlayTag?: string
46+
rounded?: boolean | string
47+
show?: Booleanish
48+
spinnerSmall?: Booleanish
49+
spinnerType?: SpinnerType
50+
spinnerVariant?: ColorVariant
51+
variant?:
52+
| 'transparent'
53+
| 'white'
54+
| 'light'
55+
| 'dark'
56+
| 'primary'
57+
| 'secondary'
58+
| 'success'
59+
| 'danger'
60+
| 'warning'
61+
| 'info' // ColorVariant | 'white' | 'transparent'
62+
wrapTag?: string
63+
zIndex?: number | string
64+
}
65+
66+
const props = withDefaults(defineProps<Props>(), {
67+
blur: '2px',
68+
fixed: false,
69+
noCenter: false,
70+
noFade: false,
71+
noWrap: false,
72+
opacity: 0.85,
73+
overlayTag: 'div',
74+
rounded: false,
75+
show: false,
76+
spinnerSmall: false,
77+
spinnerType: 'border',
78+
variant: 'light',
79+
wrapTag: 'div',
80+
zIndex: 10,
81+
})
1182
12-
interface ISlotScope {
13-
spinnerType: string | null
14-
spinnerVariant: string | null
15-
spinnerSmall: boolean
83+
interface Emits {
84+
(e: 'click', value: MouseEvent): void
85+
(e: 'hidden'): void
86+
(e: 'shown'): void
1687
}
1788
18-
export default defineComponent({
19-
components: {BTransition},
20-
props: {
21-
bgColor: {type: String, required: false},
22-
blur: {type: String, default: '2px'},
23-
fixed: {type: [Boolean, String] as PropType<Booleanish>, default: false},
24-
noCenter: {type: [Boolean, String] as PropType<Booleanish>, default: false},
25-
noFade: {type: [Boolean, String] as PropType<Booleanish>, default: false},
26-
// If `true, does not render the default slot
27-
// and switches to absolute positioning
28-
noWrap: {type: [Boolean, String] as PropType<Booleanish>, default: false},
29-
opacity: {
30-
type: [Number, String],
31-
default: 0.85,
32-
validator: (value: number | string) => {
33-
const number = toFloat(value, 0)
34-
return number >= 0 && number <= 1
35-
},
36-
},
37-
overlayTag: {type: String, default: 'div'},
38-
rounded: {type: [Boolean, String], default: false},
39-
show: {type: [Boolean, String] as PropType<Booleanish>, default: false},
40-
spinnerSmall: {type: [Boolean, String] as PropType<Booleanish>, default: false},
41-
spinnerType: {type: String, default: 'border'},
42-
spinnerVariant: {type: String, required: false},
43-
variant: {type: String as PropType<ColorVariant>, default: 'light'},
44-
wrapTag: {type: String, default: 'div'},
45-
zIndex: {type: [Number, String], default: 10},
46-
},
47-
emits: ['click', 'hidden', 'shown'],
48-
setup(props, {slots, emit}) {
49-
const fixedBoolean = useBooleanish(toRef(props, 'fixed'))
50-
const noCenterBoolean = useBooleanish(toRef(props, 'noCenter'))
51-
const noFadeBoolean = useBooleanish(toRef(props, 'noFade'))
52-
const noWrapBoolean = useBooleanish(toRef(props, 'noWrap'))
53-
const showBoolean = useBooleanish(toRef(props, 'show'))
54-
const spinnerSmallBoolean = useBooleanish(toRef(props, 'spinnerSmall'))
55-
56-
const computedRounded = computed(() =>
57-
props.rounded === true || props.rounded === ''
58-
? 'rounded'
59-
: !props.rounded
60-
? ''
61-
: `rounded-${props.rounded}`
62-
)
63-
64-
const computedVariant = computed(() =>
65-
props.variant && !props.bgColor ? `bg-${props.variant}` : ''
66-
)
67-
68-
const computedSlotScope = computed(() => ({
69-
spinnerType: props.spinnerType || null,
70-
spinnerVariant: props.spinnerVariant || null,
71-
spinnerSmall: spinnerSmallBoolean.value,
72-
}))
73-
74-
return () => {
75-
const defaultOverlayFn = (scope: ISlotScope) =>
76-
h(resolveComponent('BSpinner'), {
77-
type: scope.spinnerType,
78-
variant: scope.spinnerVariant,
79-
small: spinnerSmallBoolean.value,
80-
})
81-
82-
let $overlay: any = ''
83-
84-
if (showBoolean.value) {
85-
const $background = h('div', {
86-
class: ['position-absolute', computedVariant.value, computedRounded.value],
87-
style: {
88-
...POSITION_COVER,
89-
opacity: props.opacity,
90-
backgroundColor: props.bgColor || null,
91-
backdropFilter: props.blur ? `blur(${props.blur})` : null,
92-
},
93-
})
94-
95-
const $content = h(
96-
'div',
97-
{
98-
class: 'position-absolute',
99-
style: noCenterBoolean.value
100-
? {...POSITION_COVER}
101-
: {top: '50%', left: '50%', transform: 'translateX(-50%) translateY(-50%)'},
102-
},
103-
normalizeSlot(SLOT_NAME_OVERLAY, computedSlotScope.value, slots) ||
104-
defaultOverlayFn(computedSlotScope.value) ||
105-
''
106-
)
107-
108-
$overlay = h(
109-
props.overlayTag,
110-
{
111-
class: [
112-
'b-overlay',
113-
{
114-
'position-absolute':
115-
!noWrapBoolean.value || (noWrapBoolean.value && !fixedBoolean.value),
116-
'position-fixed': noWrapBoolean.value && fixedBoolean.value,
117-
},
118-
],
119-
style: {
120-
...POSITION_COVER,
121-
zIndex: props.zIndex || 10,
122-
},
123-
onClick: (event: MouseEvent) => emit('click', event),
124-
key: 'overlay',
125-
},
126-
[$background, $content]
127-
)
128-
}
89+
const emit = defineEmits<Emits>()
90+
91+
const positionStyles = {top: 0, left: 0, bottom: 0, right: 0}
92+
93+
const fixedBoolean = useBooleanish(toRef(props, 'fixed'))
94+
const noCenterBoolean = useBooleanish(toRef(props, 'noCenter'))
95+
const noFadeBoolean = useBooleanish(toRef(props, 'noFade'))
96+
const noWrapBoolean = useBooleanish(toRef(props, 'noWrap'))
97+
const showBoolean = useBooleanish(toRef(props, 'show'))
98+
const spinnerSmallBoolean = useBooleanish(toRef(props, 'spinnerSmall'))
99+
100+
const computedRounded = computed(() =>
101+
props.rounded === true || props.rounded === ''
102+
? 'rounded'
103+
: props.rounded === false
104+
? ''
105+
: `rounded-${props.rounded}`
106+
)
129107
130-
const getOverlayTransition = () =>
131-
h(
132-
BTransition,
133-
{
134-
noFade: noFadeBoolean.value,
135-
transProps: {enterToClass: 'show'},
136-
name: 'fade',
137-
onAfterEnter: () => emit('shown'),
138-
onAfterLeave: () => emit('hidden'),
139-
},
140-
{default: () => $overlay}
141-
)
142-
143-
if (noWrapBoolean.value) return getOverlayTransition()
144-
145-
const wrapper = h(
146-
props.wrapTag,
147-
{
148-
'class': ['b-overlay-wrap position-relative'],
149-
'aria-busy': showBoolean.value ? 'true' : null,
150-
},
151-
[h('span', normalizeSlot(SLOT_NAME_DEFAULT, {}, slots)), getOverlayTransition()]
152-
)
153-
return wrapper
154-
}
108+
const computedVariant = computed(() =>
109+
props.variant && !props.bgColor ? `bg-${props.variant}` : ''
110+
)
111+
112+
const computedAriaBusy = computed(() => (showBoolean.value ? 'true' : null))
113+
114+
const spinnerAttrs = computed(() => ({
115+
type: props.spinnerType || undefined,
116+
variant: props.spinnerVariant || undefined,
117+
small: spinnerSmallBoolean.value,
118+
}))
119+
120+
const overlayStyles = computed(() => ({
121+
...positionStyles,
122+
zIndex: props.zIndex || 10,
123+
}))
124+
125+
const overlayClasses = computed(() => [
126+
'b-overlay',
127+
{
128+
'position-absolute': !noWrapBoolean.value || !fixedBoolean.value,
129+
'position-fixed': noWrapBoolean.value && fixedBoolean.value,
155130
},
156-
})
131+
])
132+
133+
const blurClasses = computed(() => [computedVariant.value, computedRounded.value])
134+
135+
const blurStyles = computed(() => ({
136+
...positionStyles,
137+
opacity: props.opacity,
138+
backgroundColor: props.bgColor || undefined,
139+
backdropFilter: blur ? `blur(${blur})` : undefined,
140+
}))
141+
142+
const spinWrapperStyles = computed(() =>
143+
noCenterBoolean.value
144+
? positionStyles
145+
: {
146+
top: '50%',
147+
left: '50%',
148+
transform: 'translateX(-50%) translateY(-50%)',
149+
}
150+
)
157151
</script>

0 commit comments

Comments
 (0)