From dd9f5adc2e771f3602461ae708d44536f146b902 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 28 Jan 2018 10:29:15 +0100 Subject: Initial Ledger support implementation --- packages/website/ts/components/ui/drop_down.tsx | 110 ++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 packages/website/ts/components/ui/drop_down.tsx (limited to 'packages/website/ts/components/ui/drop_down.tsx') diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx new file mode 100644 index 000000000..31a67f0d7 --- /dev/null +++ b/packages/website/ts/components/ui/drop_down.tsx @@ -0,0 +1,110 @@ +import * as _ from 'lodash'; +import Menu from 'material-ui/Menu'; +import Popover, { PopoverAnimationVertical } from 'material-ui/Popover'; +import * as React from 'react'; +import { MaterialUIPosition, Styles, WebsitePaths } from 'ts/types'; +import { colors } from 'ts/utils/colors'; + +const CHECK_CLOSE_POPOVER_INTERVAL_MS = 300; +const DEFAULT_STYLE = { + fontSize: 14, +}; + +interface DropDownProps { + hoverActiveNode: React.ReactNode; + popoverContent: React.ReactNode; + anchorOrigin: MaterialUIPosition; + targetOrigin: MaterialUIPosition; + style?: React.CSSProperties; + zDepth?: number; +} + +interface DropDownState { + isDropDownOpen: boolean; + anchorEl?: HTMLInputElement; +} + +export class DropDown extends React.Component { + public static defaultProps: Partial = { + style: DEFAULT_STYLE, + zDepth: 1, + }; + private _isHovering: boolean; + private _popoverCloseCheckIntervalId: number; + constructor(props: DropDownProps) { + super(props); + this.state = { + isDropDownOpen: false, + }; + } + public componentDidMount() { + this._popoverCloseCheckIntervalId = window.setInterval(() => { + this._checkIfShouldClosePopover(); + }, CHECK_CLOSE_POPOVER_INTERVAL_MS); + } + public componentWillUnmount() { + window.clearInterval(this._popoverCloseCheckIntervalId); + } + public componentWillReceiveProps(nextProps: DropDownProps) { + // HACK: If the popoverContent is updated to a different dimension and the users + // mouse is no longer above it, the dropdown can enter an inconsistent state where + // it believes the user is still hovering over it. In order to remedy this, we + // call hoverOff whenever the dropdown receives updated props. This is a hack + // because it will effectively close the dropdown on any prop update, barring + // dropdowns from having dynamic content. + this._onHoverOff(); + } + public render() { + return ( +
+ {this.props.hoverActiveNode} + +
+ {this.props.popoverContent} +
+
+
+ ); + } + private _onHover(event: React.FormEvent) { + this._isHovering = true; + this._checkIfShouldOpenPopover(event); + } + private _checkIfShouldOpenPopover(event: React.FormEvent) { + if (this.state.isDropDownOpen) { + return; // noop + } + + this.setState({ + isDropDownOpen: true, + anchorEl: event.currentTarget, + }); + } + private _onHoverOff() { + this._isHovering = false; + } + private _checkIfShouldClosePopover() { + if (!this.state.isDropDownOpen || this._isHovering) { + return; // noop + } + this._closePopover(); + } + private _closePopover() { + this.setState({ + isDropDownOpen: false, + }); + } +} -- cgit