-
-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bidirectional communication between the tldraw and python #12
Comments
import ipyreact
from traitlets import Unicode
from IPython.display import display
class TldrawWidget(ipyreact.ReactWidget):
my_text = Unicode("Hello World").tag(sync=True)
my_text_out = Unicode("Hello World").tag(sync=True)
_esm = """
import { TDShapeType, Tldraw } from "@tldraw/tldraw";
import * as React from "react";
export default function App({ my_text, my_text_out }) {
const [app, setApp] = React.useState()
const handleMount = React.useCallback((app: Tldraw) => {
setApp(app)
}, []);
React.useEffect(() => {
if (app) {
app.createShapes({
id: "text1",
type: TDShapeType.Text,
point: [100, 100],
text: my_text,
});
}
}, [my_text, app])
return (
<div
style={{
position: "relative",
width: "800px",
height: "350px",
}}
>
<Tldraw onMount={handleMount} onChange={e => my_text_out = "updated" }/>
</div>
);
}
"""
tldraw = TldrawWidget()
tldraw.my_text = "This is Tldrawesome!!🎉"
tldraw.my_text_out = "This is Tldrawesome!!🎉"
display(tldraw) |
^^ pasted during our call, but that should be enough to get you going! Basically you want to run a side effect whenever those props change, and in that side effect you'd want to interface with the tldraw imperative API ( |
I experimented a bit more, and it seems that the onChange method in |
+1. I was hoping to find bidirectional communication. I was playing around with Panel and AnyWidget examples. TlDraw with bidirectional communication would be amazing to have access to. # pip install panel ipywidgets_bokeh tldraw
from tldraw import TldrawWidget
widget = TldrawWidget()
# HELP FUNCTIONALITY to convert Traitlets Classes/ Events to Param Classes/ Events
import anywidget
import param
_ipywidget_classes = {}
_any_widget_traits = set(anywidget.AnyWidget().traits())
def create_observer(obj, traits=None)->param.Parameterized:
"""Returns a Parameterized class with parameters corresponding to the traits of the obj
Args:
traits: A list of traits to observe. If None all traits not on the base AnyWidget will be
observed.
"""
if not traits:
traits = list(set(obj.traits())-_any_widget_traits)
print(traits)
name = type(obj).__name__
if name in _ipywidget_classes:
observer_class = _ipywidget_classes[name]
else:
observer_class = param.parameterized_class(name, {trait: param.Parameter() for trait in traits})
_ipywidget_classes[name] = observer_class
values = {trait: getattr(obj, trait) for trait in traits}
observer = observer_class(**values)
obj.observe(lambda event: setattr(observer, event["name"], event["new"]), names=traits)
return observer
# THE PANEL APP
import panel as pn
pn.extension("ipywidgets")
observer = create_observer(widget)
def some_output(value):
print(value)
return value
component = pn.Column(widget, pn.bind(some_output, observer.param.value))
pn.template.FastListTemplate(
site="Panel",
title="Works with Jupyter-TlDraw",
main=[component],
).servable() |
Bidirectional communication between python and tldraw would be amazing to have!
Here are three use cases that I can see:
Here is an example of how I imagine bidirectional communication could look like:
I've set up the JupyterLite notebook https://kolibril13.github.io/jupyter-tldraw/lab/?path=idea_bidirectional_communication.ipynb for investigation.
WARNING: All Code of this JupyterLite instance will be deleted on reload, so code should be copy+pasted to a save place before closing that page.
Brainstorming on how to get there:
The text was updated successfully, but these errors were encountered: