UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

171 lines (154 loc) 4.18 kB
import { cloneVNode, defineComponent, h, PropType, ref, watch } from 'vue' import { createPopper } from '@popperjs/core' import { isRTL } from '../../utils' const CPicker = defineComponent({ name: 'CPicker', props: { /** * Set container type for the component. */ container: { type: String as PropType<'dropdown' | 'inline'>, default: 'dropdown', }, /** * Toggle the disabled state for the component. */ disabled: Boolean, /** * A string of all className you want applied to the dropdown menu. */ dropdownClassNames: String, /** * Toggle visibility of footer element or set the content of footer. */ footer: Boolean, /** * Toggle the visibility of the component. */ visible: Boolean, }, emits: [ /** * Callback fired when the component requests to be hidden. */ 'hide', /** * Callback fired when the component requests to be shown. */ 'show', ], setup(props, { attrs, emit, slots }) { const pickerRef = ref() const dropdownRef = ref() const togglerRef = ref() const popper = ref() const visible = ref(props.visible) watch( () => props.visible, () => { visible.value = props.visible }, ) watch(visible, () => { if (props.container === 'inline') { return } if (visible.value) { emit('show') window.addEventListener('mouseup', handleMouseUp) window.addEventListener('keyup', handleKeyUp) initPopper() return } emit('hide') window.removeEventListener('mouseup', handleMouseUp) window.removeEventListener('keyup', handleKeyUp) destroyPopper() }) const initPopper = () => { if (togglerRef.value && dropdownRef.value) { popper.value = createPopper(togglerRef.value, dropdownRef.value, { placement: isRTL(pickerRef.value) ? 'bottom-end' : 'bottom-start', modifiers: [ { name: 'preventOverflow', options: { boundary: 'clippingParents', }, }, { name: 'offset', options: { offset: [0, 2], }, }, ], }) } } const destroyPopper = () => { if (popper.value) { popper.value.destroy() } popper.value = undefined } const handleKeyUp = (event: KeyboardEvent) => { if (event.key === 'Escape') { visible.value = false } } const handleMouseUp = (event: Event) => { if (pickerRef.value && pickerRef.value.contains(event.target as HTMLElement)) { return } visible.value = false } switch (props.container) { case 'inline': { return () => h('div', { class: 'picker', ref: pickerRef }, slots.default && slots.default()) } default: { return () => h( 'div', { class: [ attrs.class, { show: visible.value, }, ], ref: pickerRef, }, [ /** * @slot Location for the toggler element. */ slots.toggler && slots.toggler().map((slot) => cloneVNode(slot, { onClick: () => { if (!props.disabled && !visible.value) { visible.value = true } }, ref: (el) => { togglerRef.value = el }, }), ), h('div', { class: props.dropdownClassNames, ref: dropdownRef }, [ slots.default && slots.default(), /** * @slot Location for the footer element. */ props.footer && slots.footer && slots.footer(), ]), ], ) } } }, }) export { CPicker }