import { cloneDeep } from "lodash-es" ; import * as React from "react" ; import { Classes , Icon , Intent , TreeNodeInfo , Tree } from "@blueprintjs/core" ; import { Classes as Popover2Classes , ContextMenu2 , Tooltip2 } from "@blueprintjs/popover2" ; import { ExampleCard } from "./ExampleCard" ; type NodePath = number [ ] ; type TreeAction = { type : "SET_IS_EXPANDED" ; payload : { path : NodePath ; isExpanded : boolean ; } ; } | { type : "DESELECT_ALL" ; } | { type : "SET_IS_SELECTED" ; payload : { path : NodePath ; isSelected : boolean ; } ; } ; function forEachNode ( nodes , callback ) { if ( nodes === undefined ) { return ; } for ( const node of nodes ) { callback ( node ) ; forEachNode ( node . childNodes , callback ) ; } } function forNodeAtPath ( nodes , path , callback ) { callback ( Tree . nodeFromPath ( path , nodes ) ) ; } function treeExampleReducer ( state , action ) { switch ( action . type ) { case "DESELECT_ALL" : const newState1 = cloneDeep ( state ) ; forEachNode ( newState1 , node => ( node . isSelected = false ) ) ; return newState1 ; case "SET_IS_EXPANDED" : const newState2 = cloneDeep ( state ) ; forNodeAtPath ( newState2 , action . payload . path , node => ( node . isExpanded = action . payload . isExpanded ) ) ; return newState2 ; case "SET_IS_SELECTED" : const newState3 = cloneDeep ( state ) ; forNodeAtPath ( newState3 , action . payload . path , node => ( node . isSelected = action . payload . isSelected ) ) ; return newState3 ; default : return state ; } } export const TreeExample = _props => { const [ nodes , dispatch ] = React . useReducer ( treeExampleReducer , INITIAL_STATE ) ; const handleNodeClick = React . useCallback ( ( node , nodePath , e ) => { const originallySelected = node . isSelected ; if ( ! e . shiftKey ) { dispatch ( { type : "DESELECT_ALL" } ) ; } dispatch ( { payload : { path : nodePath , isSelected : originallySelected == null ? true : ! originallySelected } , type : "SET_IS_SELECTED" , } ) ; } , [ ] ) ; const handleNodeCollapse = React . useCallback ( ( _node , nodePath ) => { dispatch ( { payload : { path : nodePath , isExpanded : false } , type : "SET_IS_EXPANDED" , } ) ; } , [ ] ) ; const handleNodeExpand = React . useCallback ( ( _node , nodePath ) => { dispatch ( { payload : { path : nodePath , isExpanded : true } , type : "SET_IS_EXPANDED" , } ) ; } , [ ] ) ; return ( < ExampleCard label = "Tree" width = { 400 } > < Tree contents = { nodes } onNodeClick = { handleNodeClick } onNodeCollapse = { handleNodeCollapse } onNodeExpand = { handleNodeExpand } className = { Classes . ELEVATION_0 } / > < /ExampleCard>); } ; const contentSizing = { popoverProps : { popoverClassName : Popover2Classes . POPOVER2_CONTENT_SIZING } } ; const INITIAL_STATE = [ { id : 0 , hasCaret : true , icon : "folder-close" , label : ( < ContextMenu2 { ... contentSizing } content = { < div > Hello there ! < / div > } > Folder 0 < /ContextMenu2>), } , { id : 1 , icon : "folder-close" , isExpanded : true , label : ( < ContextMenu2 { ... contentSizing } content = { < div > Hello there ! < /div>}> < Tooltip2 content = "I'm a folder <3" placement = "right" > Folder 1 < /Tooltip2> < /ContextMenu2>), childNodes : [ { id : 2 , icon : "document" , label : "Item 0" , secondaryLabel : ( < Tooltip2 content = "An eye!" > < Icon icon = "eye-open" /> < /Tooltip2>), } , { id : 3 , icon : < Icon icon = "tag" intent = { Intent . PRIMARY } className = { Classes . TREE_NODE_ICON } / > , label : "Primary icon item" , } , { id : 4 , icon : < Icon icon = "endorsed" intent = { Intent . SUCCESS } className = { Classes . TREE_NODE_ICON } / > , label : "Success icon item" , } , { id : 5 , icon : < Icon icon = "warning-sign" intent = { Intent . WARNING } className = { Classes . TREE_NODE_ICON } / > , label : "Warning icon item" , } , { id : 6 , icon : < Icon icon = "error" intent = { Intent . DANGER } className = { Classes . TREE_NODE_ICON } / > , label : "Danger icon item" , } , { id : 7 , hasCaret : true , icon : "folder-close" , label : ( < ContextMenu2 { ... contentSizing } content = { < div > Hello there ! < / div > } > < Tooltip2 content = "foo" placement = "right" > Folder 2 < /Tooltip2> < /ContextMenu2>), childNodes : [ { id : 8 , label : "No-Icon Item" } , { id : 9 , icon : "tag" , label : "Item 1" } , { id : 10 , hasCaret : true , icon : "folder-close" , label : ( < ContextMenu2 { ... contentSizing } content = { < div > Hello there ! < / div > } > Folder 3 < /ContextMenu2>), childNodes : [ { id : 11 , icon : "document" , label : "Item 0" } , { id : 12 , icon : "tag" , label : "Item 1" } , ] , } , ] , } , ] , } , { id : 2 , hasCaret : true , icon : "folder-close" , label : "Super secret files" , disabled : true , } , ] ;