UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

109 lines (106 loc) 3.38 kB
import { ref, computed, watch, onUnmounted } from 'vue'; import { usePopper } from './usePopper.js'; import isRTL from '../utils/isRTL.js'; const useDropdownWithPopper = (popperConfig) => { // References to the dropdown elements const dropdownRefElement = ref(null); const dropdownMenuElement = ref(null); // Reactive state to control dropdown visibility const isOpen = ref(false); // Popper.js integration const { popper, initPopper, destroyPopper } = usePopper(); // Computed Popper configuration based on RTL and user-provided settings const _popperConfig = computed(() => ({ placement: (isRTL(dropdownRefElement.value) ? 'bottom-end' : 'bottom-start'), modifiers: [ { name: 'preventOverflow', options: { boundary: 'clippingParents', }, }, { name: 'offset', options: { offset: [0, 2], }, }, ], ...popperConfig, })); // Methods to control dropdown state const closeDropdown = () => { isOpen.value = false; }; const openDropdown = () => { isOpen.value = true; }; const toggleDropdown = () => { isOpen.value = !isOpen.value; }; const updatePopper = () => { if (popper) { popper.update(); } }; // Event handlers const handleKeyUp = (event) => { if (event.key === 'Escape') { isOpen.value = false; return; } if (event.key === 'Tab') { const activeElement = document.activeElement; if (dropdownRefElement.value?.contains(activeElement) || dropdownMenuElement.value?.contains(activeElement)) { return; } isOpen.value = false; } }; const handleMouseUp = (event) => { const target = event.target; if (dropdownMenuElement.value?.contains(target) || dropdownRefElement.value?.contains(target)) { return; } isOpen.value = false; }; // Utility functions to manage event listeners const addEventListeners = () => { window.addEventListener('mouseup', handleMouseUp); window.addEventListener('keyup', handleKeyUp); }; const removeEventListeners = () => { window.removeEventListener('mouseup', handleMouseUp); window.removeEventListener('keyup', handleKeyUp); }; // Watcher to handle side effects when `isOpen` changes watch(isOpen, (open) => { if (open) { addEventListeners(); if (dropdownRefElement.value && dropdownMenuElement.value) { initPopper(dropdownRefElement.value, dropdownMenuElement.value, _popperConfig.value); } } else { removeEventListeners(); destroyPopper(); } }); // Cleanup on component unmount onUnmounted(() => { removeEventListeners(); destroyPopper(); }); return { dropdownRefElement, dropdownMenuElement, isOpen, closeDropdown, openDropdown, toggleDropdown, updatePopper, }; }; export { useDropdownWithPopper }; //# sourceMappingURL=useDropdownWithPopper.js.map