Spaces:
Runtime error
Runtime error
import React, { ReactNode } from "react" | |
import { | |
withStreamlitConnection, | |
StreamlitComponentBase, | |
Streamlit, | |
} from "./streamlit" | |
import { Runtime, Inspector } from "@observablehq/runtime"; | |
class Observable extends StreamlitComponentBase<{}> { | |
public observeValue = {}; | |
private notebookRef = React.createRef<HTMLDivElement>(); | |
private runtime: any = null; | |
private main: any = null; | |
componentWillUnmount() { | |
this.runtime?.dispose(); | |
} | |
// @ts-ignore | |
public componentDidUpdate(prevProps: any) { | |
const { args: prevArgs } = prevProps; | |
if (prevArgs.notebook !== this.props.args.notebook) { | |
// TODO handle new notebook | |
} | |
console.log('this.props.args.redefine: ', this.props.args.redefine); | |
if (this.main !== null) { | |
this.redefineCells(this.main, this.props.args.redefine); | |
} | |
} | |
async embedNotebook(notebook: string, targets: string[], observe: string[], hide:string[]) { | |
if (this.runtime) { | |
this.runtime.dispose(); | |
} | |
console.log('Console says hi!'); | |
const targetSet = new Set(targets); | |
const observeSet = new Set(observe); | |
const hideSet = new Set(hide); | |
this.runtime = new Runtime(); | |
const { default: define } = await eval(`import("https://api.observablehq.com/${notebook}.js?v=3")`); | |
this.main = this.runtime.module(define, (name: string) => { | |
console.log('name: ', name); | |
console.log('observeSet.has(name: ', observeSet.has(name)); | |
console.log('targetSet.has(name): ', targetSet.has(name)); | |
if (observeSet.has(name) && !targetSet.has(name)) { | |
const observeValue = this.observeValue; | |
console.log('observeValue: ', observeValue); | |
return { | |
fulfilled: (value: any) => { | |
//@ts-ignore | |
observeValue[name] = value; | |
//@ts-ignore | |
Streamlit.setComponentValue(observeValue); | |
} | |
} | |
} | |
if (targetSet.size > 0 && !targetSet.has(name)) return; | |
if(hideSet.has(name)) return true; | |
const el = document.createElement('div'); | |
this.notebookRef.current?.appendChild(el); | |
const i = new Inspector(el); | |
el.addEventListener('input', e => { | |
Streamlit.setFrameHeight(); | |
}) | |
return { | |
pending() { | |
i.pending(); | |
Streamlit.setFrameHeight(); | |
}, | |
fulfilled(value: any) { | |
i.fulfilled(value); | |
Streamlit.setFrameHeight(); | |
}, | |
rejected(error: any) { | |
i.rejected(error); | |
Streamlit.setFrameHeight(); | |
}, | |
}; | |
}); | |
if (observeSet.size > 0) { | |
Promise.all(Array.from(observeSet).map(async name => [name, await this.main.value(name)])).then(initial => { | |
for (const [name, value] of initial) { | |
// @ts-ignore | |
this.observeValue[name] = value | |
}; | |
Streamlit.setComponentValue(this.observeValue); | |
}) | |
} | |
} | |
redefineCells(main: any, redefine = {}) { | |
console.log('Console says hi 2 !'); | |
for (let cell in redefine) { | |
//@ts-ignore | |
main.redefine(cell, redefine[cell]); | |
} | |
} | |
componentDidMount() { | |
const { notebook, targets = [], observe = [], redefine = {} , hide=[]} = this.props.args; | |
Streamlit.setComponentValue(this.observeValue); | |
this.embedNotebook(notebook, targets, observe, hide).then(() => { | |
this.redefineCells(this.main, redefine); | |
}); | |
} | |
public render = (): ReactNode => { | |
console.log('this.props.args.render_empty: ', this.props.args.render_empty); | |
if (this.props.args.render_empty) { | |
return ( | |
<div > | |
<div style={{ padding: '9px 12px' }}> | |
<div ref={this.notebookRef}></div> | |
</div> | |
<div style={{ marginTop: '4px' }}> | |
<div > | |
<div style={{textAlign:"left"}}>{this.props.args.name}</div> | |
<div style={{textAlign:"right"}}> | |
<a href={`https://observablehq.com/${this.props.args.notebook}`} style={{ color: '#666', }}></a> | |
</div> | |
</div> | |
</div> | |
</div > | |
) | |
} | |
return ( | |
<div style={{ border: '1px solid gray', borderRadius: '4px' }}> | |
<div style={{ padding: '9px 12px' }}> | |
<div ref={this.notebookRef}></div> | |
</div> | |
<div style={{ marginTop: '4px' }}> | |
<div style={{ | |
backgroundColor: '#ddd', | |
fontWeight: 700, | |
padding: ".25rem .5rem", | |
borderRadius: '0 0 4px 4px', | |
gridTemplateColumns: "auto auto", | |
display:"grid" | |
}}> | |
<div style={{textAlign:"left"}}>{this.props.args.name}</div> | |
<div style={{textAlign:"right"}}> | |
<a href={`https://observablehq.com/${this.props.args.notebook}`} style={{ color: '#666', }}></a> | |
</div> | |
</div> | |
</div> | |
</div > | |
) | |
} | |
} | |
export default withStreamlitConnection(Observable) | |