1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- import React, { useRef, useState, useCallback, useEffect } from 'react';
- import { CSSTransition } from 'react-transition-group';
- import styles from './Dropdown.module.css';
- export const Item = ({ value, display, onSelect, children }) => (
- <div className={styles.item} onClick={() => onSelect(value ?? children, display ?? value ?? children)}>
- {children ?? display ?? value}
- </div>
- );
- export const Dropdown = ({ open, onSelect, onClick, children }) => {
- const transitionRef = useRef(null);
- const [ displayed, setDisplayed ] = useState(null);
- const onSelectCallback = useCallback((value, display) => {
- setDisplayed(display);
- onSelect(value);
- }, [onSelect]);
- useEffect(() => {
- if (displayed) {
- return;
- }
- let found = null;
- children.forEach(element => {
- if (React.isValidElement(element) && !found && element.props['default']) {
- const { value, display } = element.props;
- found = display ?? value;
- }
- });
- setDisplayed(found);
- }, [children, displayed]);
- return (
- <div className={styles.container}>
- <div className={styles.button} onClick={onClick}>{displayed}</div>
- <CSSTransition nodeRef={transitionRef} in={open} timeout={200} mountOnEnter unmountOnExit classNames={{
- enter: styles['list-enter'],
- enterActive: styles['list-enter-active'],
- exit: styles['list-exit'],
- exitActive: styles['list-exit-active'],
- }}>
- <div className={styles.list} ref={transitionRef}>
- {children.map((child, key) => React.cloneElement(child, { onSelect: onSelectCallback, key }))}
- </div>
- </CSSTransition>
- </div>
- )
- };
- export const DropdownGroup = ({ children }) => {
- const [ open, setOpen ] = useState(null);
- return (
- <>
- {
- children.map((child, key) => React.cloneElement(child, {
- open: open === child.props.open,
- onClick: () => setOpen(o => o === child.props.open ? null : child.props.open),
- onSelect: v => { child.props.onSelect(v); setOpen(null); },
- key,
- }))
- }
- </>
- );
- }
|