import * as React from 'react'; import * as PropTypes from 'prop-types'; import { PopoverProps as ReakitPopoverProps } from 'reakit/ts/Popover/Popover'; import { InlineBlock } from '../primitives'; import Pane from '../Pane'; import { isFunction } from '../_utils/assert'; import { Omit } from '../types'; import PopoverContainer, { PopoverContainerProps, PopoverContainerRenderProps } from './PopoverContainer'; import PopoverClose, { PopoverCloseProps } from './PopoverClose'; import PopoverPopover, { LocalPopoverPopoverProps, PopoverPopoverProps, popoverPopoverDefaultProps, popoverPopoverPropTypes } from './PopoverPopover'; import PopoverShow, { PopoverShowProps } from './PopoverShow'; import PopoverHide, { PopoverHideProps } from './PopoverHide'; import PopoverToggle, { PopoverToggleProps } from './PopoverToggle'; export type LocalPopoverProps = LocalPopoverPopoverProps & { children: | React.ReactNode | (({ use, ...args }: PopoverContainerRenderProps & { use: React.ReactElement }) => React.ReactNode); className?: string; content: | string | React.ReactElement | (({ initialFocusRef, ...args }: { initialFocusRef?: React.RefObject } & PopoverContainerRenderProps) => React.ReactNode); isFullWidth?: boolean; /** Displays a cross button in the top right corner of the popover content. */ showCloseButton?: boolean; }; export type PopoverProps = Omit & LocalPopoverProps; export type PopoverComponents = { Popover: React.FunctionComponent; Container: React.FunctionComponent; Close: React.FunctionComponent; Hide: React.FunctionComponent; Show: React.FunctionComponent; Toggle: React.FunctionComponent; }; export const Popover: React.FunctionComponent & PopoverComponents = ({ children, content, isFullWidth, showCloseButton, ...props }) => ( {popover => ( {isFunction(children) ? /* // @ts-ignore */ children({ use: PopoverToggle, ...popover }) : children ? React.cloneElement(children as React.ReactElement, { use: PopoverToggle, ...popover }) : null} {({ initialFocusRef }) => ( {showCloseButton && } {/* eslint-disable-line */} {typeof content === 'function' ? content({ initialFocusRef, ...popover }) : content} )} )} ); Popover.Popover = PopoverPopover; Popover.Container = PopoverContainer; Popover.Close = PopoverClose; Popover.Hide = PopoverHide; Popover.Show = PopoverShow; Popover.Toggle = PopoverToggle; export const popoverPropTypes = { ...popoverPopoverPropTypes, className: PropTypes.string, children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired as PropTypes.Validator< LocalPopoverProps['children'] >, content: PropTypes.oneOfType([PropTypes.string, PropTypes.element, PropTypes.func]) as PropTypes.Validator< LocalPopoverProps['content'] >, isFullWidth: PropTypes.bool, showCloseButton: PropTypes.bool }; Popover.propTypes = popoverPropTypes; export const popoverDefaultProps = { ...popoverPopoverDefaultProps, children: undefined, className: undefined, isFullWidth: false, showCloseButton: false }; Popover.defaultProps = popoverDefaultProps; // @ts-ignore const C: React.FunctionComponent & PopoverComponents = Popover; export default C;