Skip to content
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

Add support for defining custom JavaScript widgets #64

Merged
merged 6 commits into from
Dec 24, 2021

Conversation

jonatanklosko
Copy link
Member

@jonatanklosko jonatanklosko commented Dec 23, 2021

This introduces JavaScript powered widgets, which allow users to build arbitrary output visualizations and interactions.

It is an extremely exciting change, because it adds a powerful extension point to Livebook. To give more context, so far Livebook defined very specific output types that it supported, so for Vega-Lite we would have a dedicated output type and would include the necessary JavaScript in Livebook. With this new feature we can effectively remove all Vega-Lite specific bits from Livebook, because it is easily implemented within the new abstraction. Similarly, users can build integrations with arbitrary JavaScript packages without Livebook knowing anything about those.

Kino provides abstractions for defining those JavaScript widgets, both static (with static data) and live (with server process). Live widgets support bidirectional communication between the JavaScript part and the Elixir part.

To learn about the API and examples read Kino.JS, then Kino.JS.Live, then the linked notebook.

js_widgets.mp4

Notebook available here.

Closes #44.

Also see livebook-dev/livebook#818.

The returned data is passed to the JavaScript `init` function
of the connecting client.
"""
@callback handle_connect(ctx :: Context.t()) :: {:ok, data :: term(), ctx :: Context.t()}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we should probably make origin available in handle_connect and handle_event to have a way of distinguishing clients. It could be an argument or a map with metadata (in case we want to add more info in the future). Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Map with metadata sounds good to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to have this information in the context, so you don't need to pass extra arguments on handle_connect and handle_event.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting idea, my only concern would be that conceptually ctx is information about the server state, which is shared across all clients. But then it's already called context so it can be anything 🙈

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way is fine by me. Just adding options. IMO it is fine for ctx to have the information about what triggered the callback. :D

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, one thing is that for callbacks other than handle_connect and handle_event it would be nil, but that's probably fine. In the end it's only useful in specific cases, so I like not needing to match-ignore it most of the time :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ctx.origin in 147be93.

@josevalim
Copy link
Contributor

This is amazing!!! The example notebook is fantastic!!!!!

lib/kino/js.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
lib/kino/js/live.ex Outdated Show resolved Hide resolved
@jeregrine
Copy link

This is amazing! Great work!

Copy link
Contributor

@josevalim josevalim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! We can add the export feature in a following PR?

@jonatanklosko
Copy link
Member Author

We can add the export feature in a following PR?

Sounds good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Question] - Steps to create new component
3 participants