diff --git a/.flowconfig b/.flowconfig index c0f52e6d66..ef46c95a41 100644 --- a/.flowconfig +++ b/.flowconfig @@ -13,6 +13,7 @@ flow [options] +esproposal.class_instance_fields=enable suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe suppress_comment=\\(.\\|\n\\)*\\$FlowIssue diff --git a/frontend/Container.js b/frontend/Container.js index 5f621863ab..ca07f3ef14 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -19,6 +19,14 @@ var TabbedPane = require('./TabbedPane'); import type MenuItem from './ContextMenu'; +type Props = {}; + +type State = { + isVertical: boolean, +}; + +var IS_VERTICAL_BREAKPOINT = 500; + class Container extends React.Component { props: { reload: () => void, @@ -37,14 +45,54 @@ class Container extends React.Component { }, extraTabs: {[key: string]: () => React$Element}, }; + state: State; + resizeTimeout: ?number; + + constructor(props: Props) { + super(props); + + this.state = { + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), + }; + } + + componentDidMount() { + window.addEventListener('resize', this.handleResize, false); + this.setState({ + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), + }); + } + + componentWillUnmount() { + window.removeEventListener('resize', this.handleResize); + clearTimeout(this.resizeTimeout); + } + + // $FlowFixMe future versions of Flow can infer this + handleResize = (e: Event): void => { + if (!this.resizeTimeout) { + this.resizeTimeout = setTimeout(this.handleResizeTimeout, 50); + } + }; + + // $FlowFixMe future versions of Flow can infer this + handleResizeTimeout = (): void => { + this.resizeTimeout = null; + + this.setState({ + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), + }); + }; render() { var tabs = { Elements: () => ( } right={() => } + isVertical={this.state.isVertical} /> ), ...this.props.extraTabs, diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index 77bcbc8740..2e0eafe84e 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -21,13 +21,18 @@ type Props = { left: () => React$Element, right: () => React$Element, initialWidth: number, + initialHeight: number, + isVertical: bool, }; -type DefaultProps = {}; +type DefaultProps = { + isVertical: true, +}; type State = { moving: boolean, width: number, + height: number, }; class SplitPane extends React.Component { @@ -40,29 +45,47 @@ class SplitPane extends React.Component { this.state = { moving: false, width: props.initialWidth, + height: props.initialHeight, }; } - onMove(x: number) { + componentDidMount() { var node = ReactDOM.findDOMNode(this); + this.setState({ - width: (node.offsetLeft + node.offsetWidth) - x, + width: this.props.isVertical ? node.offsetWidth * 0.3 : node.offsetWidth * 0.6, + height: node.offsetHeight * 0.3, }); } + onMove(x: number, y: number) { + var node = ReactDOM.findDOMNode(this); + + this.setState(prevState => ({ + width: !this.props.isVertical ? prevState.width : (node.offsetLeft + node.offsetWidth) - x, + height: this.props.isVertical ? prevState.height : (node.offsetTop + node.offsetHeight) - y, + })); + } + render() { var rightStyle = assign({}, styles.rightPane, { - width: this.state.width, + width: this.props.isVertical ? this.state.width : '100%', + height: this.props.isVertical ? '100%' : this.state.height, + marginLeft: (this.props.isVertical) ? 0 : -3, }); + + var containerStyles = this.props.isVertical ? styles.container : styles.containerVertical; + var draggerStyles = this.props.isVertical ? styles.dragger : styles.draggerVertical; + return ( -
+
{this.props.left()}
this.setState({moving: true})} - onMove={x => this.onMove(x)} + onMove={(x, y) => this.onMove(x, y)} onStop={() => this.setState({moving: false})}>
@@ -81,6 +104,13 @@ var styles = { flex: 1, }, + containerVertical: { + display: 'flex', + minWidth: 0, + flex: 1, + flexDirection: 'column', + }, + dragger: { padding: '0 3px', cursor: 'ew-resize', @@ -88,6 +118,14 @@ var styles = { zIndex: 1, }, + draggerVertical: { + backgroundColor: '#efefef', + padding: '3px 0', + cursor: 'ns-resize', + position: 'relative', + zIndex: 1, + }, + draggerInner: { backgroundColor: '#ccc', height: '100%', @@ -97,14 +135,18 @@ var styles = { rightPane: { display: 'flex', marginLeft: -3, + minWidth: 100, + minHeight: 100, padding: 5, }, leftPane: { display: 'flex', marginRight: -3, - minWidth: '255px', + minWidth: '50%', + minHeight: '50%', flex: 1, + borderBottom: '1px solid #ccc', }, }; diff --git a/frontend/detail_pane/DetailPane.js b/frontend/detail_pane/DetailPane.js index fe5b0042bb..3ef53f943e 100644 --- a/frontend/detail_pane/DetailPane.js +++ b/frontend/detail_pane/DetailPane.js @@ -45,6 +45,7 @@ var styles = { userSelect: 'none', }, header: { + backgroundColor: '#efefef', padding: 5, flexShrink: 0, display: 'flex', diff --git a/plugins/Relay/QueriesTab.js b/plugins/Relay/QueriesTab.js index 3dec0bd9b4..a70058a3ef 100644 --- a/plugins/Relay/QueriesTab.js +++ b/plugins/Relay/QueriesTab.js @@ -28,8 +28,10 @@ class QueriesTab extends React.Component { contents = ( } right={() => } + isVertical={false} /> ); }