import React, { useEffect, useRef } from 'react'; import DropdownBase, { DropdownBaseProps, } from '@digigov/react-core/DropdownBase'; export * from '@digigov/react-core/DropdownButton'; export * from '@digigov/react-core/DropdownContent'; export interface DropdownProps extends DropdownBaseProps { /** * Use closeBehaviour to set the way that the Dropdown will close. */ closeBehaviour?: 'clickButton' | 'clickOutside'; /** * Use float dropdown to set the dropdown to float over * scroll bars and stay on a static position. * This is mainly used to show actions in a long table. */ float?: boolean; } /** * Dropdown component is used for showing more options with a button. */ export const Dropdown = React.forwardRef( function Dropdown( { closeBehaviour = 'clickOutside', float = false, ...props }, ref ) { const innerRef = useRef(null); useEffect(() => { const element = innerRef.current; if (!element) { return; } const keyDownHandler = (event) => { if (event.key === 'Escape') { element.open = false; event.preventDefault(); } }; const handleClickOutside = (event) => { if (element && !element.contains(event.target)) { element.open = false; } }; if (closeBehaviour === 'clickOutside') { document.addEventListener('click', handleClickOutside, true); } document.addEventListener('keydown', keyDownHandler); const toggleFloat = () => { const tbody = element.closest('tbody') as HTMLElement; const parentElement = element?.parentElement as HTMLElement; if (element.open) { tbody.style.position = 'inherit'; const rect = element?.getBoundingClientRect(); const parentRect = parentElement.getBoundingClientRect(); const top = rect.top + window.pageYOffset; const left = rect.left + window.pageXOffset; parentElement.style.height = `${parentRect.height}px`; parentElement.style.width = `${parentRect.width}px`; element.style.top = `${top}px`; element.style.left = `${left}px`; element.style.position = `absolute`; element.style.display = `block`; element.style.background = 'inherit'; } else { tbody.style.position = 'relative'; parentElement.style.height = ''; parentElement.style.width = ''; element.style.top = `0`; element.style.left = `0`; element.style.position = `relative`; element.style.display = `table-cell`; } }; if (float) { element.addEventListener('toggle', toggleFloat); } return () => { if (closeBehaviour === 'clickOutside') { document.removeEventListener('click', handleClickOutside, true); } if (float) { element.removeEventListener('toggle', toggleFloat); } document.removeEventListener('keydown', keyDownHandler); }; }, []); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return ( { innerRef.current = el; if (typeof ref === 'function') { ref(el); } }} {...props} /> ); } ); export { DropdownBase }; export default Dropdown;