From 19de45f5dffa8aba210bdf2e510ac9e0a0d61a69 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Wed, 10 Oct 2018 20:34:41 -0700 Subject: [PATCH] Tyep PlaylistMenu --- .../{PlaylistMenu.js => PlaylistMenu.tsx} | 64 +++++++------------ .../PlaylistWindow/PlaylistMenuEntry.tsx | 50 +++++++++++++++ 2 files changed, 72 insertions(+), 42 deletions(-) rename js/components/PlaylistWindow/{PlaylistMenu.js => PlaylistMenu.tsx} (54%) create mode 100644 js/components/PlaylistWindow/PlaylistMenuEntry.tsx diff --git a/js/components/PlaylistWindow/PlaylistMenu.js b/js/components/PlaylistWindow/PlaylistMenu.tsx similarity index 54% rename from js/components/PlaylistWindow/PlaylistMenu.js rename to js/components/PlaylistWindow/PlaylistMenu.tsx index e82a993f..dadb05bc 100644 --- a/js/components/PlaylistWindow/PlaylistMenu.js +++ b/js/components/PlaylistWindow/PlaylistMenu.tsx @@ -1,62 +1,42 @@ import React from "react"; import classnames from "classnames"; -let cursorX; -let cursorY; -window.document.addEventListener("mousemove", e => { - cursorX = e.pageX; - cursorY = e.pageY; -}); +import PlaylistMenuEnry from "./PlaylistMenuEntry"; -// We implement hover ourselves, because we hate ourselves and https://stackoverflow.com/a/13259049/1263117 -class Entry extends React.Component { - constructor(props) { - super(props); - this.state = { hover: false }; - } - - componentDidMount() { - const domRect = this.node.getBoundingClientRect(); - this.setState({ - hover: - cursorX >= domRect.left && - cursorX <= domRect.right && - cursorY >= domRect.top && - cursorY <= domRect.bottom - }); - } - - render() { - return ( -
  • (this.node = node)} - onMouseEnter={() => this.setState({ hover: true })} - onMouseLeave={() => this.setState({ hover: false })} - className={classnames({ hover: this.state.hover })} - > - {this.props.children} -
  • - ); - } +interface Props { + id: string; } -export default class PlaylistMenu extends React.Component { - constructor(props) { +interface State { + selected: boolean; +} + +export default class PlaylistMenu extends React.Component { + constructor(props: Props) { super(props); this.state = { selected: false }; } - _handleClick = e => { + _handleClick = (e: React.MouseEvent) => { const { target } = e; + if (!(target instanceof Element)) { + // TypeScript doesn't realize this will always be true + return; + } const { selected } = this.state; if (selected) { this.setState({ selected: false }); return; } - const handleClickOut = ee => { + const handleClickOut = (ee: MouseEvent) => { + const clickOutTarget = ee.target; + if (!(clickOutTarget instanceof Element)) { + // TypeScript doesn't realize this will always be true + return; + } // If the click is _not_ inside the menu. - if (!target.contains(ee.target)) { + if (!target.contains(clickOutTarget)) { // If we've clicked on a Context Menu spawed inside this menu, it will // register as an external click. However, hiding the menu will remove // the Context Menu from the DOM. Therefore, we wait until the next @@ -90,7 +70,7 @@ export default class PlaylistMenu extends React.Component { {this.state.selected && (
      {React.Children.map(this.props.children, (child, i) => ( - {child} + {child} ))}
    )} diff --git a/js/components/PlaylistWindow/PlaylistMenuEntry.tsx b/js/components/PlaylistWindow/PlaylistMenuEntry.tsx new file mode 100644 index 00000000..8e84812b --- /dev/null +++ b/js/components/PlaylistWindow/PlaylistMenuEntry.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import classnames from "classnames"; + +interface Props {} + +interface State { + hover: boolean; +} +let cursorX: number; +let cursorY: number; +window.document.addEventListener("mousemove", e => { + cursorX = e.pageX; + cursorY = e.pageY; +}); + +// We implement hover ourselves, because we hate ourselves and https://stackoverflow.com/a/13259049/1263117 +export default class PlaylistMenuEntry extends React.Component { + node?: HTMLLIElement | null; + constructor(props: Props) { + super(props); + this.state = { hover: false }; + } + + componentDidMount() { + if (this.node == null) { + return; + } + const domRect = this.node.getBoundingClientRect(); + this.setState({ + hover: + cursorX >= domRect.left && + cursorX <= domRect.right && + cursorY >= domRect.top && + cursorY <= domRect.bottom + }); + } + + render() { + return ( +
  • (this.node = node)} + onMouseEnter={() => this.setState({ hover: true })} + onMouseLeave={() => this.setState({ hover: false })} + className={classnames({ hover: this.state.hover })} + > + {this.props.children} +
  • + ); + } +}