import { h, cloneElement, Component, VNode, createRef, ComponentChildren, ComponentProps } from "preact"; import { ClickOutsideDetector } from "../ClickOutsideDetector"; import * as style from './style.css'; import 'add-css:./style.css'; type Anchor = 'left' | 'right' | 'top' | 'bottom'; interface Props extends ComponentProps<'aside'> { showing?: boolean; direction?: 'up' | 'down'; anchor?: Anchor | Anchor[]; toggle?: VNode; children?: ComponentChildren; } interface State { showing: boolean; } export default class Flyout extends Component { state = { showing: this.props.showing === true }; private menu = createRef(); private hide = () => { this.setState({ showing: false }); }; private toggle = () => { this.setState({ showing: !this.state.showing }); }; componentWillReceiveProps({ showing }: Props) { if (showing !== this.props.showing) { this.setState({ showing }); } } componentDidUpdate(prevProps: Props, prevState: State) { if (this.state.showing && !prevState.showing) { const menu = this.menu.current; if (menu) { let toFocus = menu.firstElementChild; for (let child of menu.children) { if (child.hasAttribute('autofocus')) { toFocus = child; break; } } // @ts-ignore-next if (toFocus) toFocus.focus(); } } } render({ direction, anchor, toggle, children, ...props }: Props, { showing }: State) { const toggleProps = { flyoutOpen: showing, onClick: this.toggle }; const anchorText = Array.isArray(anchor) ? anchor.join(' ') : anchor; return ( {toggle && cloneElement(toggle, toggleProps)} ); } }