mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-22 06:15:47 +00:00
117 lines
2.5 KiB
TypeScript
117 lines
2.5 KiB
TypeScript
'use client';
|
|
|
|
import { ReactNode, useRef, useEffect, useState } from 'react';
|
|
import { cn } from '@/lib/helper';
|
|
|
|
interface DropdownProps {
|
|
trigger: ReactNode;
|
|
children: ReactNode;
|
|
position?:
|
|
| 'top'
|
|
| 'bottom'
|
|
| 'left'
|
|
| 'right'
|
|
| 'top-start'
|
|
| 'top-end'
|
|
| 'bottom-start'
|
|
| 'bottom-end'
|
|
| 'left-start'
|
|
| 'left-end'
|
|
| 'right-start'
|
|
| 'right-end';
|
|
align?: 'start' | 'center' | 'end';
|
|
hover?: boolean;
|
|
className?: string;
|
|
contentClassName?: string;
|
|
}
|
|
|
|
const Dropdown = ({
|
|
trigger,
|
|
children,
|
|
position = 'bottom',
|
|
align = 'start',
|
|
hover = false,
|
|
className,
|
|
contentClassName,
|
|
}: DropdownProps) => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
|
|
// Handle click outside to close dropdown
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (
|
|
dropdownRef.current &&
|
|
!dropdownRef.current.contains(event.target as Node)
|
|
) {
|
|
setIsOpen(false);
|
|
}
|
|
};
|
|
|
|
if (isOpen) {
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
}
|
|
|
|
return () => {
|
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
};
|
|
}, [isOpen]);
|
|
|
|
// Build position classes
|
|
const getPositionClasses = () => {
|
|
const classes: string[] = [];
|
|
|
|
// Handle combined positions like 'top-start'
|
|
if (position.includes('-')) {
|
|
const [pos, al] = position.split('-');
|
|
classes.push(`dropdown-${pos}`);
|
|
classes.push(`dropdown-${al}`);
|
|
} else {
|
|
classes.push(`dropdown-${position}`);
|
|
if (align !== 'start') {
|
|
classes.push(`dropdown-${align}`);
|
|
}
|
|
}
|
|
|
|
return classes.join(' ');
|
|
};
|
|
|
|
const handleToggle = (e: React.MouseEvent) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
// alert('clicked');
|
|
setIsOpen(!isOpen);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
ref={dropdownRef}
|
|
className={cn(
|
|
'dropdown',
|
|
getPositionClasses(),
|
|
hover && 'dropdown-hover',
|
|
isOpen && 'dropdown-open',
|
|
className
|
|
)}
|
|
>
|
|
{/* Trigger Button */}
|
|
<div onClick={handleToggle} className='cursor-pointer'>
|
|
{trigger}
|
|
</div>
|
|
|
|
{/* Dropdown Content - Only render when open */}
|
|
{isOpen && (
|
|
<div
|
|
tabIndex={-1}
|
|
className={cn('dropdown-content z-[10]', contentClassName)}
|
|
onClick={() => setIsOpen(false)} // Close on item click
|
|
>
|
|
{children}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Dropdown;
|