/* eslint-disable default-case */ import React, { useLayoutEffect, useRef, useState } from 'react' import { styled } from '@styled-components' import { BoxProps } from '../../atoms/box/index.js' const StyledDropDown = styled.div` position: relative; display: inline-block; ` export const DEFAULT_STICK = 'left' /** * Available values for {@link DropDown}.stick prop * @memberof DropDown */ export type DropDownStickProp = 'left' | 'right' /** * Props passed to DropDown element. * @property {string} [...] Other props from {@link BoxProps} * @memberof DropDown * @extends BoxProps */ export type DropDownProps = { /** Indicates if menu should stick to left or right */ stick?: DropDownStickProp; children?: React.ReactNode; } & BoxProps type PositionProps = { left?: number, right?: number, top: number, } /** * @load ./drop-down.doc.md * @hideconstructor * @see {@link https://storybook.adminjs.co/?path=/story/designsystem-molecules-dropdown--default Storybook} * @component * @subcategory Molecules * @section design-system */ const DropDown: React.FC = (props) => { const { children, stick = DEFAULT_STICK, ...boxProps } = props const [isVisible, setIsVisible] = useState(false) const [initialHeight, setInitialHeight] = useState(null) const ref = useRef(null) const [menuPosition, setMenuPosition] = useState() useLayoutEffect(() => { if (ref.current && !initialHeight) { const { offsetHeight } = ref.current setInitialHeight(offsetHeight) switch (stick) { case 'left': setMenuPosition({ left: 0, top: offsetHeight }) break case 'right': setMenuPosition({ right: 0, top: offsetHeight }) } } }, [ref.current]) const elements = React.Children.map(children, (child: any) => { const type = child && child.type && child.type.displayName if (type === 'DropDownTrigger') { // getting rid of DropDownTrigger and render just what was inside return React.cloneElement(child.props.children) } if (type === 'DropDownMenu') { return React.cloneElement(child, { isVisible, stick, ...menuPosition, }) } return child }) return ( setIsVisible(true)} onMouseLeave={(): void => setIsVisible(false)} ref={ref} > {elements} ) } DropDown.displayName = 'DropDown' export { DropDown } export default DropDown