import { number , withKnobs } from '@storybook/addon-knobs' ; import { storiesOf } from '@storybook/react' ; import React , { FC } from 'react' ; import AutoSizer from 'react-virtualized-auto-sizer' ; import { FixedSizeNodeData , FixedSizeNodePublicState , FixedSizeTree , TreeWalker , TreeWalkerValue , } from '../src' ; import { NodeComponentProps } from '../src/Tree' ; document . body . style . margin = '0' ; document . body . style . display = 'flex' ; document . body . style . minHeight = '100vh' ; const root = document . getElementById ( 'root' ) ! ; root . style . margin = '10px 0 0 10px' ; root . style . flex = '1' ; type TreeNode = Readonly < { children : TreeNode [ ] ; id : number ; name : string ; } > ; type TreeData = FixedSizeNodeData & Readonly < { isLeaf : boolean ; name : string ; nestingLevel : number ; } > ; let nodeId = 0 ; const createNode = ( depth = 0 ) : TreeNode => { const node = { children : [ ] , id : nodeId , name : `test-${ nodeId }` , } ; nodeId += 1 ; if ( depth === 5 ) { return node ; } for ( let i = 0 ; i < 10 ; i ++ ) { node . children . push ( createNode ( depth + 1 ) ) ; } return node ; } ; const rootNode = createNode ( ) ; const defaultTextStyle = { marginLeft : 10 } ; const defaultButtonStyle = { fontFamily : 'Courier New' } ; type NodeMeta = Readonly < { nestingLevel : number ; node : TreeNode ; } > ; const getNodeData = ( node , nestingLevel ) : TreeWalkerValue < TreeData , NodeMeta > => ( { data : { id : node . id . toString ( ) , isLeaf : node . children . length === 0 , isOpenByDefault : true , name : node . name , nestingLevel , } , nestingLevel , node , } ) ; function * treeWalker ( ) { for ( let i = 0 ; i < rootNode . children . length ; i ++ ) { yield getNodeData ( rootNode . children [ i ] , 0 ) ; } while ( true ) { const parentMeta = yield ; for ( let i = 0 ; i < parentMeta . node . children . length ; i ++ ) { yield getNodeData ( parentMeta . node . children [ i ] , parentMeta . nestingLevel + 1 ) ; } } } const Node = ( { data : { isLeaf , name , nestingLevel } , isOpen , style , setOpen } ) => ( < div style = { { ... style , alignItems : 'center' , display : 'flex' , marginLeft : nestingLevel * 30 + ( isLeaf ? 48 : 0 ) , } } > { ! isLeaf && ( < div > < button type = "button" onClick = { ( ) => setOpen ( ! isOpen ) } style = { defaultButtonStyle } > { isOpen ? '-' : '+' } < /button> < /div>)} < div style = { defaultTextStyle } > { name } < /div> < /div>); type TreePresenterProps = Readonly < { itemSize : number ; } > ; const TreePresenter = ( { itemSize } ) => { return ( < AutoSizer disableWidth > { ( { height } ) => ( < FixedSizeTree treeWalker = { treeWalker } itemSize = { itemSize } height = { height } width = "100%" > { Node } < /FixedSizeTree>)} < /AutoSizer>); } ; storiesOf ( 'Tree' , module ) . addDecorator ( withKnobs ) . add ( 'Multiple Tree roots' , ( ) => ( < TreePresenter itemSize = { number ( 'Row height' , 30 ) } / > ) ) ;