controlled-dropdown.tsx 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import React, {
  2. Children,
  3. cloneElement,
  4. type FC,
  5. isValidElement,
  6. useCallback,
  7. } from 'react'
  8. import { Dropdown, DropdownProps } from 'react-bootstrap'
  9. import useDropdown from '../hooks/use-dropdown'
  10. type ControlledDropdownProps = DropdownProps & {
  11. defaultOpen?: boolean
  12. onMainButtonClick?: (dropdownOpen: boolean) => void
  13. }
  14. const ControlledDropdown: FC<ControlledDropdownProps> = ({
  15. defaultOpen,
  16. onMainButtonClick,
  17. ...props
  18. }) => {
  19. const { onClick, ...dropdownProps } = useDropdown(Boolean(defaultOpen))
  20. const handleClick = useCallback(
  21. (e: React.MouseEvent<Dropdown, MouseEvent>) => {
  22. onClick(e)
  23. if (onMainButtonClick) {
  24. onMainButtonClick(dropdownProps.open)
  25. }
  26. },
  27. [onClick, onMainButtonClick, dropdownProps.open]
  28. )
  29. return (
  30. <Dropdown {...props} {...dropdownProps} onClick={handleClick}>
  31. {Children.map(props.children, child => {
  32. if (!isValidElement(child)) {
  33. return child
  34. }
  35. // Dropdown.Menu
  36. if ('open' in child.props) {
  37. return cloneElement<any>(child, { open: dropdownProps.open })
  38. }
  39. // Overlay
  40. if ('show' in child.props) {
  41. return cloneElement<any>(child, { show: dropdownProps.open })
  42. }
  43. // anything else
  44. return cloneElement(child)
  45. })}
  46. </Dropdown>
  47. )
  48. }
  49. export default ControlledDropdown