glass-app-manager
Version:
Informatica's Glass Framework CLI for bootstrapping
64 lines (53 loc) • 1.91 kB
JavaScript
// @flow
import * as React from "react";
import Popover from "react-tiny-popover";
import ArrowContainer from "react-tiny-popover/dist/ArrowContainer";
export type PopupProps = {
/**
* Set `true` to open the popup by default. Use this when
* you want to _control_ when the popup is open or not.
*/
isOpen?: boolean,
/**
* Specify a custom trigger. This makes the popup _uncontrolled_
* and state will be handled internally.
*/
trigger: React.Element<any>,
/**
* Specify the content of the popup.
*/
children: React.Node,
/**
* When popup is uncontrolled, specify how you want the user to interact
* with the popup.
*/
on: "click" | "focus" | "hover",
};
const getEventProps = (on, setOpen, toggle) => ({
...(on.indexOf("hover") !== -1
? {
onMouseEnter: () => setOpen(true),
onMouseLeave: () => setOpen(false),
}
: {}),
...(on.indexOf("focus") !== -1
? {
onFocus: () => setOpen(true),
onBlur: () => setOpen(false),
}
: {}),
onClick: on.indexOf("click") !== -1 ? toggle : undefined,
});
export default function Popup({ isOpen, trigger, children, on = "", ...rest }: PopupProps) {
const [internalIsOpen, setInternalIsOpen] = React.useState(false);
const triggers = React.useMemo(
() => getEventProps(on, setInternalIsOpen, () => setInternalIsOpen(!internalIsOpen)),
[internalIsOpen, on, setInternalIsOpen]
);
return (
<Popover containerClassName="popup-container" containerStyle={{overflow: "visible"}} {...rest} isOpen={isOpen || internalIsOpen}>
{trigger ? React.cloneElement(trigger, { ...triggers }) : children}
</Popover>
);
}
Popup.ArrowContainer = ArrowContainer;