import React , { CSSProperties , useState , useRef , useEffect , ReactNode , createContext , useCallback , } from 'react' ; import cytoscape from 'cytoscape' ; import dagre from 'cytoscape-dagre' ; import { EuiThemeType } from '../../../../components/color_range_legend' ; import { getCytoscapeOptions } from './cytoscape_options' ; cytoscape . use ( dagre ) ; export const CytoscapeContext = createContext < cytoscape . Core | undefined > ( undefined ) ; interface CytoscapeProps { children ? : ReactNode ; elements : cytoscape . ElementDefinition [ ] ; theme : EuiThemeType ; height : number ; itemsDeleted : boolean ; resetCy : boolean ; style ? : CSSProperties ; width : number ; } function useCytoscape ( options ) { const [ cy , setCy ] = useState < cytoscape . Core | undefined > ( ) ; const ref = useRef ( null ) ; useEffect ( ( ) => { if ( ! cy ) { setCy ( cytoscape ( { ... options , container : ref . current } ) ) ; } } , [ options , cy ] ) ; useEffect ( ( ) => { return ( ) => { if ( cy ) { cy . destroy ( ) ; } } ; } , [ cy ] ) ; return [ ref , cy ] as [ React . MutableRefObject < any > , cytoscape . Core | undefined ] ; } function getLayoutOptions ( width , height ) { return { name : 'dagre' , rankDir : 'LR' , fit : true , padding : 20 , spacingFactor : 0.95 , boundingBox : { x1 : 0 , y1 : 0 , w : width , h : height } , } ; } export function Cytoscape ( { children , elements , theme , height , itemsDeleted , resetCy , style , width , } ) { const [ ref , cy ] = useCytoscape ( { ... getCytoscapeOptions ( theme ) , elements , } ) ; const divStyle = { ... style , height } ; const dataHandler = useCallback < cytoscape . EventHandler > ( ( event ) => { if ( cy && height > 0 ) { setTimeout ( ( ) => cy . layout ( getLayoutOptions ( width , height ) ) . run ( ) , 150 ) ; } } , [ cy , height , width ] ) ; useEffect ( ( ) => { if ( cy ) { cy . on ( 'data' , dataHandler ) ; } return ( ) => { if ( cy ) { cy . removeListener ( 'data' , undefined , dataHandler as cytoscape . EventHandler ) ; } } ; } , [ cy , elements , height , width ] ) ; useEffect ( ( ) => { if ( cy ) { if ( itemsDeleted === false ) { cy . add ( elements ) ; } else { cy . elements ( ) . remove ( ) ; cy . add ( elements ) ; } cy . trigger ( 'data' ) ; } } , [ cy , elements ] ) ; useEffect ( ( ) => { if ( cy ) { cy . reset ( ) ; } } , [ cy , resetCy ] ) ; return ( < CytoscapeContext . Provider value = { cy } > < div ref = { ref } style = { divStyle } data - test - subj = "mlPageDataFrameAnalyticsMapCytoscape" > { children } < /div> < /CytoscapeContext.Provider>); }