2016-08-08 04:27:53 -07:00
/ * *
* Copyright ( c ) 2016 - present , Facebook , Inc .
* All rights reserved .
*
* This source code is licensed under the BSD - style license found in the
* LICENSE file in the root directory of this source tree . An additional grant
* of patent rights can be found in the PATENTS file in the same directory .
* /
'use strict' ;
/*eslint no-console-disallow: "off"*/
/*global React:true*/
// TODO:
// selection and arrow keys for navigating
2016-08-16 06:55:48 -07:00
var _createClass = function ( ) { function defineProperties ( target , props ) { for ( var i = 0 ; i < props . length ; i ++ ) { var descriptor = props [ i ] ; descriptor . enumerable = descriptor . enumerable || false ; descriptor . configurable = true ; if ( "value" in descriptor ) descriptor . writable = true ; Object . defineProperty ( target , descriptor . key , descriptor ) ; } } return function ( Constructor , protoProps , staticProps ) { if ( protoProps ) defineProperties ( Constructor . prototype , protoProps ) ; if ( staticProps ) defineProperties ( Constructor , staticProps ) ; return Constructor ; } ; } ( ) ; function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( "Cannot call a class as a function" ) ; } } function _possibleConstructorReturn ( self , call ) { if ( ! self ) { throw new ReferenceError ( "this hasn't been initialised - super() hasn't been called" ) ; } return call && ( typeof call === "object" || typeof call === "function" ) ? call : self ; } function _inherits ( subClass , superClass ) { if ( typeof superClass !== "function" && superClass !== null ) { throw new TypeError ( "Super expression must either be null or a function, not " + typeof superClass ) ; } subClass . prototype = Object . create ( superClass && superClass . prototype , { constructor : { value : subClass , enumerable : false , writable : true , configurable : true } } ) ; if ( superClass ) Object . setPrototypeOf ? Object . setPrototypeOf ( subClass , superClass ) : subClass . _ _proto _ _ = superClass ; }
2016-08-08 04:27:53 -07:00
var rowHeight = 20 ;
2016-08-16 06:55:48 -07:00
var treeIndent = 16 ; var
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
Draggable = function ( _React$Component ) { _inherits ( Draggable , _React$Component ) ; // eslint-disable-line no-unused-vars
2016-08-08 04:27:53 -07:00
function Draggable ( props ) { _classCallCheck ( this , Draggable ) ; return _possibleConstructorReturn ( this , Object . getPrototypeOf ( Draggable ) . call ( this ,
2016-08-16 06:55:48 -07:00
props ) ) ;
} _createClass ( Draggable , [ { key : 'render' , value : function render ( )
2016-08-08 04:27:53 -07:00
{
var id = this . props . id ;
function dragStart ( e ) {
2016-08-16 06:55:48 -07:00
e . dataTransfer . setData ( 'text/plain' , id ) ;
}
2016-08-08 04:27:53 -07:00
return React . cloneElement (
this . props . children ,
2016-08-16 06:55:48 -07:00
{ draggable : 'true' , onDragStart : dragStart } ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
} } ] ) ; return Draggable ; } ( React . Component ) ;
2016-08-08 04:27:53 -07:00
Draggable . propTypes = {
children : React . PropTypes . element . isRequired ,
2016-08-16 06:55:48 -07:00
id : React . PropTypes . string . isRequired } ; var
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
DropTarget = function ( _React$Component2 ) { _inherits ( DropTarget , _React$Component2 ) ; // eslint-disable-line no-unused-vars
2016-08-08 04:27:53 -07:00
function DropTarget ( props ) { _classCallCheck ( this , DropTarget ) ; return _possibleConstructorReturn ( this , Object . getPrototypeOf ( DropTarget ) . call ( this ,
2016-08-16 06:55:48 -07:00
props ) ) ;
} _createClass ( DropTarget , [ { key : 'render' , value : function render ( )
2016-08-08 04:27:53 -07:00
{
var thisId = this . props . id ;
var dropFilter = this . props . dropFilter ;
var dropAction = this . props . dropAction ;
return React . cloneElement (
this . props . children ,
{
onDragOver : function onDragOver ( e ) {
var sourceId = e . dataTransfer . getData ( 'text/plain' ) ;
if ( dropFilter ( sourceId ) ) {
2016-08-16 06:55:48 -07:00
e . preventDefault ( ) ;
}
} ,
2016-08-08 04:27:53 -07:00
onDrop : function onDrop ( e ) {
var sourceId = e . dataTransfer . getData ( 'text/plain' ) ;
if ( dropFilter ( sourceId ) ) {
e . preventDefault ( ) ;
2016-08-16 06:55:48 -07:00
dropAction ( sourceId , thisId ) ;
}
} } ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
} } ] ) ; return DropTarget ; } ( React . Component ) ;
2016-08-08 04:27:53 -07:00
DropTarget . propTypes = {
children : React . PropTypes . element . isRequired ,
id : React . PropTypes . string . isRequired ,
dropFilter : React . PropTypes . func . isRequired ,
2016-08-16 06:55:48 -07:00
dropAction : React . PropTypes . func . isRequired } ; var
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
Table = function ( _React$Component3 ) { _inherits ( Table , _React$Component3 ) ; // eslint-disable-line no-unused-vars
2016-08-08 04:27:53 -07:00
function Table ( props ) { _classCallCheck ( this , Table ) ; var _this3 = _possibleConstructorReturn ( this , Object . getPrototypeOf ( Table ) . call ( this ,
props ) ) ;
_this3 . state = {
aggrow : props . aggrow ,
2016-08-17 11:22:34 -07:00
viewport : { top : 0 , height : 100 } ,
cursor : 0 } ; return _this3 ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
} _createClass ( Table , [ { key : 'scroll' , value : function scroll (
2016-08-08 04:27:53 -07:00
e ) {
var viewport = e . target ;
var top = Math . floor ( ( viewport . scrollTop - viewport . clientHeight * 1.0 ) / rowHeight ) ;
var height = Math . ceil ( viewport . clientHeight * 3.0 / rowHeight ) ;
2016-08-17 11:22:34 -07:00
if ( top !== this . state . viewport . top || height !== this . state . viewport . height ) {
this . setState ( { viewport : { top : top , height : height } } ) ;
}
} } , { key : '_contractRow' , value : function _contractRow (
row ) {
var newCursor = this . state . cursor ;
if ( newCursor > row . top && newCursor < row . top + row . height ) { // in contracted section
newCursor = row . top ;
} else if ( newCursor >= row . top + row . height ) { // below contracted section
newCursor -= row . height - 1 ;
}
this . state . aggrow . contract ( row ) ;
this . setState ( { cursor : newCursor } ) ;
} } , { key : '_expandRow' , value : function _expandRow (
row ) {
var newCursor = this . state . cursor ;
this . state . aggrow . expand ( row ) ;
if ( newCursor > row . top ) { // below expanded section
newCursor += row . height - 1 ;
}
this . setState ( { cursor : newCursor } ) ;
} } , { key : '_keepCursorInViewport' , value : function _keepCursorInViewport ( )
{
if ( this . _scrollDiv ) {
var cursor = this . state . cursor ;
var scrollDiv = this . _scrollDiv ;
if ( cursor * rowHeight < scrollDiv . scrollTop + scrollDiv . clientHeight * 0.1 ) {
scrollDiv . scrollTop = cursor * rowHeight - scrollDiv . clientHeight * 0.1 ;
} else if ( ( cursor + 1 ) * rowHeight > scrollDiv . scrollTop + scrollDiv . clientHeight * 0.9 ) {
scrollDiv . scrollTop = ( cursor + 1 ) * rowHeight - scrollDiv . clientHeight * 0.9 ;
}
}
} } , { key : 'keydown' , value : function keydown (
e ) {
var aggrow = this . state . aggrow ;
var cursor = this . state . cursor ;
var row = aggrow . getRows ( cursor , 1 ) [ 0 ] ;
switch ( e . keyCode ) {
case 38 : // up
if ( cursor > 0 ) {
this . setState ( { cursor : cursor - 1 } ) ;
this . _keepCursorInViewport ( ) ;
}
e . preventDefault ( ) ;
break ;
case 40 : // down
if ( cursor < aggrow . getHeight ( ) - 1 ) {
this . setState ( { cursor : cursor + 1 } ) ;
this . _keepCursorInViewport ( ) ;
}
e . preventDefault ( ) ;
break ;
case 37 : // left
if ( aggrow . canContract ( row ) ) {
this . _contractRow ( row ) ;
} else if ( aggrow . getRowIndent ( row ) > 0 ) {
var indent = aggrow . getRowIndent ( row ) - 1 ;
while ( aggrow . getRowIndent ( row ) > indent ) {
cursor -- ;
row = aggrow . getRows ( cursor , 1 ) [ 0 ] ;
}
this . setState ( { cursor : cursor } ) ;
this . _keepCursorInViewport ( ) ;
}
e . preventDefault ( ) ;
break ;
case 39 : // right
if ( aggrow . canExpand ( row ) ) {
this . _expandRow ( row ) ;
} else if ( cursor < aggrow . getHeight ( ) - 1 ) {
this . setState ( { cursor : cursor + 1 } ) ;
this . _keepCursorInViewport ( ) ;
}
e . preventDefault ( ) ;
break ; }
2016-08-16 06:55:48 -07:00
} } , { key : 'dropAggregator' , value : function dropAggregator (
2016-08-08 04:27:53 -07:00
s , d ) {
var aggrow = this . state . aggrow ;
console . log ( 'dropped ' + s + ' to ' + d ) ;
if ( s . startsWith ( 'aggregate:active:' ) ) {
var sIndex = parseInt ( s . substr ( 17 ) , 10 ) ;
var dIndex = - 1 ;
var active = aggrow . getActiveAggregators ( ) ;
var dragged = active [ sIndex ] ;
if ( d . startsWith ( 'aggregate:insert:' ) ) {
2016-08-16 06:55:48 -07:00
dIndex = parseInt ( d . substr ( 17 ) , 10 ) ;
} else if ( d === 'divider:insert' ) {
dIndex = active . length ;
} else {
throw 'not allowed to drag ' + s + ' to ' + d ;
}
2016-08-08 04:27:53 -07:00
if ( dIndex > sIndex ) {
2016-08-16 06:55:48 -07:00
dIndex -- ;
}
2016-08-08 04:27:53 -07:00
active . splice ( sIndex , 1 ) ;
active . splice ( dIndex , 0 , dragged ) ;
aggrow . setActiveAggregators ( active ) ;
2016-08-17 11:22:34 -07:00
this . setState ( { cursor : 0 } ) ;
2016-08-16 06:55:48 -07:00
} else if ( s . startsWith ( 'expander:active:' ) ) {
2016-08-08 04:27:53 -07:00
var _sIndex = parseInt ( s . substr ( 16 ) , 10 ) ;
var _dIndex = - 1 ;
var _active = aggrow . getActiveExpanders ( ) ;
var _dragged = _active [ _sIndex ] ;
if ( d . startsWith ( 'expander:insert:' ) ) {
2016-08-16 06:55:48 -07:00
_dIndex = parseInt ( d . substr ( 16 ) , 10 ) ;
} else if ( d === 'divider:insert' ) {
_dIndex = 0 ;
} else {
throw 'not allowed to drag ' + s + ' to ' + d ;
}
2016-08-08 04:27:53 -07:00
if ( _dIndex > _sIndex ) {
2016-08-16 06:55:48 -07:00
_dIndex -- ;
}
2016-08-08 04:27:53 -07:00
_active . splice ( _sIndex , 1 ) ;
_active . splice ( _dIndex , 0 , _dragged ) ;
aggrow . setActiveExpanders ( _active ) ;
2016-08-17 11:22:34 -07:00
this . setState ( { cursor : 0 } ) ;
2016-08-16 06:55:48 -07:00
}
} } , { key : 'render' , value : function render ( )
2016-08-08 04:27:53 -07:00
{ var _this4 = this ;
var headers = [ ] ;
var aggrow = this . state . aggrow ;
var aggregators = aggrow . getActiveAggregators ( ) ;
var expanders = aggrow . getActiveExpanders ( ) ;
// aggregators
for ( var i = 0 ; i < aggregators . length ; i ++ ) {
var name = aggrow . getAggregatorName ( aggregators [ i ] ) ;
headers . push (
React . createElement ( DropTarget , {
id : 'aggregate:insert:' + i . toString ( ) ,
dropFilter : function dropFilter ( ) { return true ; } ,
2016-08-16 06:55:48 -07:00
dropAction : function dropAction ( s , d ) { _this4 . dropAggregator ( s , d ) ; } } ,
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
width : '16px' ,
height : 'inherit' ,
backgroundColor : 'darkGray' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ) ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
headers . push ( React . createElement ( Draggable , { id : 'aggregate:active:' + i . toString ( ) } ,
React . createElement ( 'div' , { style : { width : '128px' , textAlign : 'center' , flexShrink : '0' } } , name ) ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
}
2016-08-08 04:27:53 -07:00
headers . push (
React . createElement ( DropTarget , {
id : 'divider:insert' ,
dropFilter : function dropFilter ( ) { return true ; } ,
2016-08-16 06:55:48 -07:00
dropAction : function dropAction ( s , d ) { _this4 . dropAggregator ( s , d ) ; } } ,
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
width : '16px' ,
height : 'inherit' ,
backgroundColor : 'gold' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ) ) ) ;
2016-08-08 04:27:53 -07:00
for ( var _i = 0 ; _i < expanders . length ; _i ++ ) {
var _name = aggrow . getExpanderName ( expanders [ _i ] ) ;
var bg = _i % 2 === 0 ? 'white' : 'lightGray' ;
2016-08-16 06:55:48 -07:00
headers . push ( React . createElement ( Draggable , { id : 'expander:active:' + _i . toString ( ) } ,
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
width : '128px' ,
textAlign : 'center' ,
backgroundColor : bg ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ,
2016-08-08 04:27:53 -07:00
_name ) ) ) ;
var sep = _i + 1 < expanders . length ? '->' : '...' ;
headers . push (
React . createElement ( DropTarget , {
id : 'expander:insert:' + ( _i + 1 ) . toString ( ) ,
dropFilter : function dropFilter ( ) { return true ; } ,
2016-08-16 06:55:48 -07:00
dropAction : function dropAction ( s , d ) { _this4 . dropAggregator ( s , d ) ; } } ,
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
height : 'inherit' ,
backgroundColor : 'darkGray' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ,
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
sep ) ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
}
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
return (
React . createElement ( 'div' , { style : { width : '100%' , height : '100%' , display : 'flex' , flexDirection : 'column' } } ,
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
width : '100%' ,
height : '26px' ,
display : 'flex' ,
flexDirection : 'row' ,
alignItems : 'center' ,
2016-08-16 06:55:48 -07:00
borderBottom : '2px solid black' } } ,
2016-08-08 04:27:53 -07:00
headers ) ,
2016-08-17 11:22:34 -07:00
React . createElement ( 'div' , {
style : {
2016-08-08 04:27:53 -07:00
width : '100%' ,
flexGrow : '1' ,
overflow : 'scroll' } ,
2016-08-17 11:22:34 -07:00
onScroll : function onScroll ( e ) { return _this4 . scroll ( e ) ; } ,
ref : function ref ( div ) { _this4 . _scrollDiv = div ; } } ,
2016-08-16 06:55:48 -07:00
React . createElement ( 'div' , { style : { position : 'relative' } } ,
this . renderVirtualizedRows ( ) ) ) ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
} } , { key : 'renderVirtualizedRows' , value : function renderVirtualizedRows ( )
2016-08-08 04:27:53 -07:00
{ var _this5 = this ;
var aggrow = this . state . aggrow ;
var viewport = this . state . viewport ;
var rows = aggrow . getRows ( viewport . top , viewport . height ) ;
2016-08-16 06:55:48 -07:00
return (
2016-08-08 04:27:53 -07:00
React . createElement ( 'div' , { style : {
position : 'absolute' ,
width : '100%' ,
2016-08-16 06:55:48 -07:00
height : ( rowHeight * ( aggrow . getHeight ( ) + 20 ) ) . toString ( ) + 'px' } } ,
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
rows . map ( function ( child ) { return _this5 . renderRow ( child ) ; } ) ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
} } , { key : 'renderRow' , value : function renderRow (
2016-08-08 04:27:53 -07:00
row ) { var _this6 = this ;
if ( row === null ) {
2016-08-16 06:55:48 -07:00
return null ;
}
2016-08-08 04:27:53 -07:00
var bg = 'lightGray' ;
var aggrow = this . state . aggrow ;
var columns = [ ] ;
var rowText = '' ;
var indent = 4 + aggrow . getRowIndent ( row ) * treeIndent ;
var aggregates = aggrow . getActiveAggregators ( ) ;
if ( row . parent !== null && row . parent . expander % 2 === 0 ) {
2016-08-16 06:55:48 -07:00
bg = 'white' ;
}
2016-08-17 11:22:34 -07:00
if ( row . top === this . state . cursor ) {
bg = 'lightblue' ;
}
2016-08-08 04:27:53 -07:00
for ( var i = 0 ; i < aggregates . length ; i ++ ) {
var aggregate = aggrow . getRowAggregate ( row , i ) ;
columns . push (
React . createElement ( 'div' , { style : {
width : '16px' ,
height : 'inherit' ,
backgroundColor : 'darkGray' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ) ) ;
2016-08-08 04:27:53 -07:00
columns . push (
React . createElement ( 'div' , { style : {
width : '128px' ,
textAlign : 'right' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ,
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
aggregate ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-16 06:55:48 -07:00
}
2016-08-08 04:27:53 -07:00
columns . push (
React . createElement ( 'div' , { style : {
width : '16px' ,
height : 'inherit' ,
backgroundColor : 'gold' ,
2016-08-16 06:55:48 -07:00
flexShrink : '0' } } ) ) ;
2016-08-08 04:27:53 -07:00
if ( aggrow . canExpand ( row ) ) {
2016-08-17 11:22:34 -07:00
columns . push (
React . createElement ( 'div' , {
style : {
marginLeft : indent . toString ( ) + 'px' ,
flexShrink : '0' ,
width : '12px' ,
textAlign : 'center' ,
border : '1px solid gray' } ,
onClick : function onClick ( ) { return _this6 . _expandRow ( row ) ; } } , '+' ) ) ;
2016-08-16 06:55:48 -07:00
} else if ( aggrow . canContract ( row ) ) {
2016-08-17 11:22:34 -07:00
columns . push (
React . createElement ( 'div' , {
style : {
marginLeft : indent . toString ( ) + 'px' ,
flexShrink : '0' ,
width : '12px' ,
textAlign : 'center' ,
border : '1px solid gray' } ,
onClick : function onClick ( ) { return _this6 . _contractRow ( row ) ; } } , '-' ) ) ;
2016-08-16 06:55:48 -07:00
} else {
2016-08-17 11:22:34 -07:00
columns . push (
React . createElement ( 'div' , {
style : {
marginLeft : indent . toString ( ) + 'px' } } ) ) ;
2016-08-16 06:55:48 -07:00
}
2016-08-08 04:27:53 -07:00
rowText += aggrow . getRowLabel ( row ) ;
columns . push (
React . createElement ( 'div' , { style : {
flexShrink : '0' ,
2016-08-17 11:22:34 -07:00
whiteSpace : 'nowrap' ,
marginRight : '20px' } } ,
2016-08-08 04:27:53 -07:00
rowText ) ) ;
2016-08-16 06:55:48 -07:00
return (
2016-08-17 11:22:34 -07:00
React . createElement ( 'div' , {
key : row . top ,
style : {
2016-08-08 04:27:53 -07:00
position : 'absolute' ,
height : ( rowHeight - 1 ) . toString ( ) + 'px' ,
top : ( rowHeight * row . top ) . toString ( ) + 'px' ,
display : 'flex' ,
flexDirection : 'row' ,
2016-08-17 11:22:34 -07:00
alignItems : 'center' ,
2016-08-08 04:27:53 -07:00
backgroundColor : bg ,
borderBottom : '1px solid gray' } ,
onClick : function onClick ( ) {
2016-08-17 11:22:34 -07:00
_this6 . setState ( { cursor : row . top } ) ;
2016-08-16 06:55:48 -07:00
} } ,
columns ) ) ;
2016-08-08 04:27:53 -07:00
2016-08-17 11:22:34 -07:00
} } , { key : 'componentDidMount' , value : function componentDidMount ( )
{
this . keydown = this . keydown . bind ( this ) ;
document . body . addEventListener ( 'keydown' , this . keydown ) ;
} } , { key : 'componentWillUnmount' , value : function componentWillUnmount ( )
{
document . body . removeEventListener ( 'keydown' , this . keydown ) ;
2016-08-16 06:55:48 -07:00
} } ] ) ; return Table ; } ( React . Component ) ; // @generated