Skip to content

Commit fe1f1bc

Browse files
author
issayah
committed
BPopover script setup conversion
1 parent d3e77f2 commit fe1f1bc

File tree

3 files changed

+115
-120
lines changed

3 files changed

+115
-120
lines changed

src/components/BPopover.vue

Lines changed: 112 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -20,134 +20,128 @@
2020
</div>
2121
</template>
2222

23-
<script lang="ts">
23+
<script setup lang="ts">
24+
// import type {BPopoverEmits, BPopoverProps} from '@/types/components'
25+
import type {BPopoverDelayObject} from '@/types/components'
2426
import Popover from 'bootstrap/js/dist/popover'
25-
import {
26-
ComponentPublicInstance,
27-
computed,
28-
defineComponent,
29-
nextTick,
30-
onMounted,
31-
PropType,
32-
ref,
33-
watch,
34-
} from 'vue'
35-
import useEventListener from '../composables/useEventListener'
36-
import {ColorVariant} from '../types'
37-
interface DelayObject {
38-
show: number
39-
hide: number
27+
import {ComponentPublicInstance, computed, nextTick, onMounted, ref, useSlots, watch} from 'vue'
28+
import useEventListener from '@/composables/useEventListener'
29+
import type {ColorVariant} from '@/types'
30+
31+
interface BPopoverProps {
32+
id: string
33+
title: string
34+
content: string
35+
container?: string | ComponentPublicInstance<HTMLElement> | HTMLElement
36+
noninteractive?: boolean
37+
placement: Popover.Options['placement']
38+
target?: string | ComponentPublicInstance<HTMLElement> | HTMLElement
39+
delay?: number | BPopoverDelayObject
40+
triggers?: Popover.Options['trigger']
41+
show?: boolean
42+
variant?: ColorVariant
43+
html?: boolean
44+
sanitize?: boolean
45+
offset?: Popover.Options['offset']
4046
}
41-
export default defineComponent({
42-
name: 'BPopover',
43-
props: {
44-
container: {
45-
type: [String, Object] as PropType<
46-
string | ComponentPublicInstance<HTMLElement> | HTMLElement
47-
>,
48-
default: 'body',
49-
},
50-
content: {type: String},
51-
id: {type: String},
52-
noninteractive: {type: Boolean, default: false},
53-
placement: {type: String as PropType<Popover.Options['placement']>, default: 'right'},
54-
target: {
55-
type: [String, Object] as PropType<
56-
string | ComponentPublicInstance<HTMLElement> | HTMLElement | undefined
57-
>,
58-
default: undefined,
59-
},
60-
title: {type: String},
61-
delay: {type: [Number, Object] as PropType<number | DelayObject>, default: 0},
62-
triggers: {type: String as PropType<Popover.Options['trigger']>, default: 'click'},
63-
show: {type: Boolean, default: false},
64-
variant: {type: String as PropType<ColorVariant>, default: undefined},
65-
html: {type: Boolean, default: true},
66-
sanitize: {type: Boolean, default: false},
67-
offset: {type: String as PropType<Popover.Options['offset']>, default: '0'},
68-
},
69-
emits: ['show', 'shown', 'hide', 'hidden', 'inserted'],
70-
setup(props, {emit, slots}) {
71-
const element = ref<HTMLElement>()
72-
const target = ref<HTMLElement | undefined>()
73-
const instance = ref<Popover>()
74-
const titleRef = ref<HTMLElement>()
75-
const contentRef = ref<HTMLElement>()
76-
const classes = computed(() => ({
77-
[`b-popover-${props.variant}`]: props.variant,
78-
}))
7947
80-
const cleanElementProp = (
81-
target: string | ComponentPublicInstance<HTMLElement> | HTMLElement | undefined
82-
): HTMLElement | string | undefined => {
83-
if (typeof target === 'string') {
84-
return target
85-
} else if (target instanceof HTMLElement) return target
86-
else if (typeof target !== 'undefined')
87-
return (target as ComponentPublicInstance<HTMLElement>).$el as HTMLElement
88-
return undefined
89-
}
48+
const props = withDefaults(defineProps<BPopoverProps>(), {
49+
container: 'body',
50+
noninteractive: false,
51+
placement: 'right',
52+
target: undefined,
53+
delay: 0,
54+
triggers: 'click',
55+
show: false,
56+
variant: undefined,
57+
html: true,
58+
sanitize: false,
59+
offset: '0',
60+
})
9061
91-
const getElement = (element: HTMLElement | string | undefined): HTMLElement | undefined => {
92-
if (!element) return undefined
93-
if (typeof element === 'string') {
94-
const idElement = document.getElementById(element)
95-
return idElement ? idElement : undefined
96-
}
97-
return element
98-
}
62+
interface BPopoverEmits {
63+
(e: 'show'): void
64+
(e: 'shown'): void
65+
(e: 'hide'): void
66+
(e: 'hidden'): void
67+
(e: 'inserted'): void
68+
}
9969
100-
onMounted(() => {
101-
nextTick(() => {
102-
target.value = getElement(cleanElementProp(props.target))
70+
const emit = defineEmits<BPopoverEmits>()
10371
104-
if (target.value)
105-
instance.value = new Popover(target.value, {
106-
container: cleanElementProp(props.container),
107-
trigger: props.triggers,
108-
placement: props.placement,
109-
title: props.title || slots.title ? titleRef.value : '',
110-
content: contentRef.value,
111-
html: props.html,
112-
delay: props.delay,
113-
sanitize: props.sanitize,
114-
offset: props.offset,
115-
})
116-
else console.warn('[B-Popover] Target is a mandatory props.')
117-
})
72+
const slots = useSlots()
11873
119-
element.value?.parentNode?.removeChild(element.value)
74+
const element = ref<HTMLElement>()
75+
const target = ref<HTMLElement | undefined>()
76+
const instance = ref<Popover>()
77+
const titleRef = ref<HTMLElement>()
78+
const contentRef = ref<HTMLElement>()
79+
const classes = computed(() => ({
80+
[`b-popover-${props.variant}`]: props.variant,
81+
}))
12082
121-
if (props.show) {
122-
instance.value?.show()
123-
}
124-
})
83+
const cleanElementProp = (
84+
target: string | ComponentPublicInstance<HTMLElement> | HTMLElement | undefined
85+
): HTMLElement | string | undefined => {
86+
if (typeof target === 'string') {
87+
return target
88+
} else if (target instanceof HTMLElement) return target
89+
else if (typeof target !== 'undefined')
90+
return (target as ComponentPublicInstance<HTMLElement>).$el as HTMLElement
91+
return undefined
92+
}
12593
126-
watch(
127-
() => props.show,
128-
(show, oldVal) => {
129-
if (show !== oldVal) {
130-
if (show) {
131-
instance.value?.show()
132-
} else {
133-
instance.value?.hide()
134-
}
135-
}
136-
}
137-
)
94+
const getElement = (element: HTMLElement | string | undefined): HTMLElement | undefined => {
95+
if (!element) return undefined
96+
if (typeof element === 'string') {
97+
const idElement = document.getElementById(element)
98+
return idElement ? idElement : undefined
99+
}
100+
return element
101+
}
138102
139-
useEventListener(target, 'show.bs.popover', () => emit('show'))
140-
useEventListener(target, 'shown.bs.popover', () => emit('shown'))
141-
useEventListener(target, 'hide.bs.popover', () => emit('hide'))
142-
useEventListener(target, 'hidden.bs.popover', () => emit('hidden'))
143-
useEventListener(target, 'inserted.bs.popover', () => emit('inserted'))
103+
onMounted(() => {
104+
nextTick(() => {
105+
target.value = getElement(cleanElementProp(props.target))
144106
145-
return {
146-
element,
147-
titleRef,
148-
contentRef,
149-
classes,
150-
}
151-
},
107+
if (target.value)
108+
instance.value = new Popover(target.value, {
109+
container: cleanElementProp(props.container),
110+
trigger: props.triggers,
111+
placement: props.placement,
112+
title: props.title || slots.title ? titleRef.value : '',
113+
content: contentRef.value,
114+
html: props.html,
115+
delay: props.delay,
116+
sanitize: props.sanitize,
117+
offset: props.offset,
118+
})
119+
else console.warn('[B-Popover] Target is a mandatory props.')
120+
})
121+
122+
element.value?.parentNode?.removeChild(element.value)
123+
124+
if (props.show) {
125+
instance.value?.show()
126+
}
152127
})
128+
129+
watch(
130+
() => props.show,
131+
(show, oldVal) => {
132+
if (show !== oldVal) {
133+
if (show) {
134+
instance.value?.show()
135+
} else {
136+
instance.value?.hide()
137+
}
138+
}
139+
}
140+
)
141+
142+
useEventListener(target, 'show.bs.popover', () => emit('show'))
143+
useEventListener(target, 'shown.bs.popover', () => emit('shown'))
144+
useEventListener(target, 'hide.bs.popover', () => emit('hide'))
145+
useEventListener(target, 'hidden.bs.popover', () => emit('hidden'))
146+
useEventListener(target, 'inserted.bs.popover', () => emit('inserted'))
153147
</script>

src/types/components/BPopover.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface Props {
66
id: string
77
title: string
88
content: string
9-
container?: PropType<string | ComponentPublicInstance<HTMLElement> | HTMLElement>
9+
container?: string | ComponentPublicInstance<HTMLElement> | HTMLElement
1010
noninteractive?: boolean
1111
placement: Popover.Options['placement']
1212
target?: string | ComponentPublicInstance<HTMLElement> | HTMLElement
@@ -27,7 +27,7 @@ export interface Emits {
2727
(e: 'inserted'): void
2828
}
2929
// Other
30-
interface DelayObject {
30+
export interface DelayObject {
3131
show: number
3232
hide: number
3333
}

src/types/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export type {Emits as BOffcanvasEmits} from './BOffcanvas'
149149

150150
export type {Props as BPopoverProps} from './BPopover'
151151
export type {Emits as BPopoverEmits} from './BPopover'
152+
export type {DelayObject as BPopoverDelayObject} from './BPopover'
152153

153154
export type {Props as BProgressProps} from './BProgress'
154155

0 commit comments

Comments
 (0)