11import React , { useCallback , useContext , useEffect , useState } from 'react' ;
2- import ReactDOM from 'react-dom' ;
2+ import { createRoot } from 'react-dom/client ' ;
33import { observer } from "mobx-react-lite" ;
44import { reaction } from "mobx"
55import { GraphicWalker , PureRenderer , GraphicRenderer , TableWalker } from '@kanaries/graphic-walker'
@@ -27,6 +27,7 @@ import InitModal from './components/initModal';
2727import { getSaveTool } from './tools/saveTool' ;
2828import { getExportTool } from './tools/exportTool' ;
2929import { getExportDataframeTool } from './tools/exportDataframe' ;
30+ import { getRuncellTool } from './tools/runcellTool' ;
3031import { formatExportedChartDatas } from "./utils/save" ;
3132import { tracker } from "@/utils/tracker" ;
3233import Notification from "./notify"
@@ -50,6 +51,7 @@ import { currentMediaTheme } from './utils/theme';
5051import { AppContext , darkModeContext } from './store/context' ;
5152import FormatSpec from './utils/formatSpec' ;
5253import { getOpenDesktopTool } from './tools/openDesktop' ;
54+ import RuncellBanner from './components/runcellBanner' ;
5355
5456
5557const initChart = async ( gwRef : React . MutableRefObject < IGWHandler | null > , total : number , props : IAppProps ) => {
@@ -208,10 +210,11 @@ const ExploreApp: React.FC<IAppProps & {initChartFlag: boolean}> = (props) => {
208210 } , 0 ) ;
209211 } , [ mode ] ) ;
210212
213+ const runcellTool = getRuncellTool ( ) ;
211214 const exportTool = getExportTool ( setExportOpen ) ;
212215 const openInDesktopTool = getOpenDesktopTool ( props , storeRef ) ;
213216
214- const tools = [ exportTool , openInDesktopTool ] ;
217+ const tools = [ runcellTool , exportTool , openInDesktopTool ] ;
215218 if ( props . env && [ "jupyter_widgets" , "streamlit" , "gradio" , "marimo" , "anywidget" , "web_server" ] . indexOf ( props . env ) !== - 1 && props . useSaveTool ) {
216219 const saveTool = getSaveTool ( props , gwRef , storeRef , isChanged , setIsChanged ) ;
217220 tools . push ( saveTool ) ;
@@ -228,20 +231,25 @@ const ExploreApp: React.FC<IAppProps & {initChartFlag: boolean}> = (props) => {
228231
229232 const enhanceAPI = React . useMemo ( ( ) => {
230233 if ( props . showCloudTool ) {
231- return {
232- features : {
233- "askviz" : async ( metas : IViewField [ ] , query : string ) => {
234- const resp = await communicationStore . comm ?. sendMsg ( "get_spec_by_text" , { metas, query } ) ;
235- return resp ?. data . data ;
236- } ,
237- "vlChat" : async ( metas : IViewField [ ] , chats : IChatMessage [ ] ) => {
238- const resp = await communicationStore . comm ?. sendMsg ( "get_chart_by_chats" , { metas, chats } ) ;
239- return resp ?. data . data ;
240- }
241- }
234+ const features : Record < string , any > = { } ;
235+ if ( props . enableAskViz ) {
236+ features [ "askviz" ] = async ( metas : IViewField [ ] , query : string ) => {
237+ const resp = await communicationStore . comm ?. sendMsg ( "get_spec_by_text" , { metas, query } ) ;
238+ return resp ?. data . data ;
239+ } ;
240+ }
241+ if ( props . enableVlChat ) {
242+ features [ "vlChat" ] = async ( metas : IViewField [ ] , chats : IChatMessage [ ] ) => {
243+ const resp = await communicationStore . comm ?. sendMsg ( "get_chart_by_chats" , { metas, chats } ) ;
244+ return resp ?. data . data ;
245+ } ;
246+ }
247+ if ( Object . keys ( features ) . length > 0 ) {
248+ return { features } ;
242249 }
243250 }
244- } , [ props . showCloudTool ] ) ;
251+ return undefined ;
252+ } , [ props . showCloudTool , props . enableAskViz , props . enableVlChat ] ) ;
245253
246254 const computationCallback = React . useMemo ( ( ) => getComputationCallback ( props ) , [ ] ) ;
247255
@@ -401,6 +409,7 @@ function GWalkerComponent(props: IAppProps) {
401409
402410 return (
403411 < React . StrictMode >
412+ < RuncellBanner env = { props . env } />
404413 { props . gwMode === "explore" && < ExploreApp { ...props } dataSource = { dataSource } initChartFlag = { initChartFlag } /> }
405414 { props . gwMode === "renderer" && < PureRednererApp { ...props } dataSource = { dataSource } /> }
406415 { props . gwMode === "filter_renderer" && < GraphicRendererApp { ...props } dataSource = { dataSource } /> }
@@ -430,12 +439,14 @@ function GWalker(props: IAppProps, id: string) {
430439 }
431440
432441 preRender ( props ) . then ( ( ) => {
433- ReactDOM . render (
434- < MainApp darkMode = { props . dark } gid = { props . id } sendMessage = { props . env ?. startsWith ( "jupyter" ) } >
435- < GWalkerComponent { ...props } />
436- </ MainApp > ,
437- document . getElementById ( id )
438- ) ;
442+ const container = document . getElementById ( id ) ;
443+ if ( container ) {
444+ createRoot ( container ) . render (
445+ < MainApp darkMode = { props . dark } gid = { props . id } sendMessage = { props . env ?. startsWith ( "jupyter" ) } >
446+ < GWalkerComponent { ...props } />
447+ </ MainApp >
448+ ) ;
449+ }
439450 } )
440451}
441452
@@ -447,22 +458,26 @@ function PreviewApp(props: IPreviewProps, containerId: string) {
447458 window . document . getElementById ( containerId ) ?. remove ( ) ;
448459 }
449460
450- ReactDOM . render (
451- < MainApp darkMode = { props . dark } hideToolBar >
452- < Preview { ...props } />
453- </ MainApp > ,
454- document . getElementById ( containerId )
455- ) ;
461+ const container = document . getElementById ( containerId ) ;
462+ if ( container ) {
463+ createRoot ( container ) . render (
464+ < MainApp darkMode = { props . dark } hideToolBar >
465+ < Preview { ...props } />
466+ </ MainApp >
467+ ) ;
468+ }
456469}
457470
458471function ChartPreviewApp ( props : IChartPreviewProps , id : string ) {
459472 props . visSpec = FormatSpec ( [ props . visSpec ] , [ ] ) [ 0 ] ;
460- ReactDOM . render (
461- < MainApp darkMode = { props . dark } hideToolBar >
462- < ChartPreview { ...props } />
463- </ MainApp > ,
464- document . getElementById ( id )
465- ) ;
473+ const container = document . getElementById ( id ) ;
474+ if ( container ) {
475+ createRoot ( container ) . render (
476+ < MainApp darkMode = { props . dark } hideToolBar >
477+ < ChartPreview { ...props } />
478+ </ MainApp >
479+ ) ;
480+ }
466481}
467482
468483function GraphicRendererApp ( props : IAppProps ) {
@@ -539,7 +554,7 @@ function TableWalkerApp(props: IAppProps) {
539554function SteamlitGWalkerApp ( streamlitProps : any ) {
540555 const props = streamlitProps . args as IAppProps ;
541556 const [ inited , setInited ] = useState ( false ) ;
542- const container = React . useRef ( null ) ;
557+ const container = React . useRef < HTMLDivElement > ( null ) ;
543558 props . visSpec = FormatSpec ( props . visSpec , props . rawFields ) ;
544559
545560 useEffect ( ( ) => {
@@ -572,13 +587,15 @@ function SteamlitGWalkerApp(streamlitProps: any) {
572587} ;
573588
574589const StreamlitGWalker = ( ) => {
575- const StreamlitGWalker = withStreamlitConnection ( SteamlitGWalkerApp ) ;
576- ReactDOM . render (
577- < React . StrictMode >
578- < StreamlitGWalker />
579- </ React . StrictMode > ,
580- document . getElementById ( "root" )
581- )
590+ const StreamlitGWalkerComponent = withStreamlitConnection ( SteamlitGWalkerApp ) ;
591+ const container = document . getElementById ( "root" ) ;
592+ if ( container ) {
593+ createRoot ( container ) . render (
594+ < React . StrictMode >
595+ < StreamlitGWalkerComponent />
596+ </ React . StrictMode >
597+ ) ;
598+ }
582599}
583600
584601function AnywidgetGWalkerApp ( ) {
0 commit comments