@@ -30,6 +30,8 @@ import {
30
30
} from "@xyflow/react" ;
31
31
32
32
import "@xyflow/react/dist/style.css" ;
33
+ import { AnyModel } from "@anywidget/types" ;
34
+ import { createRoot } from "react-dom/client" ;
33
35
// Elk has a *huge* amount of options to configure. To see everything you can
34
36
// tweak check out:
35
37
//
@@ -701,7 +703,7 @@ function LayoutFlow({
701
703
) ;
702
704
}
703
705
704
- function Visualizer ( { egraph, height = null , resize = false } : { egraph : string ; height ?: string | null ; resize ?: boolean } ) {
706
+ export function Visualizer ( { egraph, height = null , resize = false } : { egraph : string ; height ?: string | null ; resize ?: boolean } ) {
705
707
const [ outerElem , setOuterElem ] = useState < HTMLDivElement | null > ( null ) ;
706
708
const [ innerElem , setInnerElem ] = useState < HTMLDivElement | null > ( null ) ;
707
709
@@ -731,4 +733,43 @@ function Visualizer({ egraph, height = null, resize = false }: { egraph: string;
731
733
) ;
732
734
}
733
735
734
- export default Visualizer ;
736
+ // Put these both in one file, so its emitted as a single chunk and anywidget doesn't have to import another file
737
+
738
+ /// Render anywidget model to the given element
739
+ // Must be named `render` to work as an anywidget module
740
+ // https://anywidget.dev/en/afm/#lifecycle-methods
741
+ // eslint-disable-next-line react-refresh/only-export-components
742
+ export function render ( { model, el } : { el : HTMLElement ; model : AnyModel } ) {
743
+ const root = createRoot ( el ) ;
744
+ function render ( ) {
745
+ startTransition ( ( ) => {
746
+ root . render ( < Visualizer egraph = { model . get ( "egraph" ) } height = "600px" resize /> ) ;
747
+ } ) ;
748
+ }
749
+ render ( ) ;
750
+ model . on ( "change:egraph" , render ) ;
751
+
752
+ return ( ) => {
753
+ model . off ( "change:egraph" , render ) ;
754
+ root . unmount ( ) ;
755
+ } ;
756
+ }
757
+
758
+ /// Mount the visualizer to the given element
759
+ /// Call `render` to render a new egraph
760
+ /// Call `unmount` to unmount the visualizer
761
+ // eslint-disable-next-line react-refresh/only-export-components
762
+ export function mount ( element : HTMLElement ) : { render : ( egraph : string ) => void ; unmount : ( ) => void } {
763
+ const root = createRoot ( element ) ;
764
+
765
+ function render ( egraph : string ) {
766
+ startTransition ( ( ) => {
767
+ root . render ( < Visualizer egraph = { egraph } /> ) ;
768
+ } ) ;
769
+ }
770
+
771
+ function unmount ( ) {
772
+ root . unmount ( ) ;
773
+ }
774
+ return { render, unmount } ;
775
+ }
0 commit comments