mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-12 06:25:56 +08:00
Use more specific scope for custom kinos (#1142)
This commit is contained in:
parent
5ee612df40
commit
94dc3862a3
3 changed files with 20 additions and 20 deletions
|
@ -24,7 +24,7 @@ We can implement it using [`Kino.JS`](https://hexdocs.pm/kino/Kino.JS.html)
|
||||||
in less than 15 LOC:
|
in less than 15 LOC:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.HTML do
|
defmodule KinoGuide.HTML do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
|
|
||||||
def new(html) when is_binary(html) do
|
def new(html) when is_binary(html) do
|
||||||
|
@ -46,7 +46,7 @@ Let's break it down.
|
||||||
To define a custom kino we need to create a new module,
|
To define a custom kino we need to create a new module,
|
||||||
conventionally under the `Kino.` prefix, so that the end
|
conventionally under the `Kino.` prefix, so that the end
|
||||||
user can easily autocomplete all available kinos. In
|
user can easily autocomplete all available kinos. In
|
||||||
this case we went with `Kino.HTML`.
|
this case we went with `KinoGuide.HTML`.
|
||||||
|
|
||||||
We start by adding `use Kino.JS`, which makes our module
|
We start by adding `use Kino.JS`, which makes our module
|
||||||
asset-aware. In particular, it allows us to use the `asset/2`
|
asset-aware. In particular, it allows us to use the `asset/2`
|
||||||
|
@ -70,7 +70,7 @@ for the end user.
|
||||||
Let's give our Kino a try:
|
Let's give our Kino a try:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
Kino.HTML.new("""
|
KinoGuide.HTML.new("""
|
||||||
<h3>Look!</h3>
|
<h3>Look!</h3>
|
||||||
|
|
||||||
<p>I wrote this HTML from <strong>Kino</strong>!</p>
|
<p>I wrote this HTML from <strong>Kino</strong>!</p>
|
||||||
|
@ -113,7 +113,7 @@ for handling any messages sent via `Kino.JS.Live.cast/2`. Here is how
|
||||||
the code will look like:
|
the code will look like:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.Leaflet do
|
defmodule KinoGuide.Leaflet do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
use Kino.JS.Live
|
use Kino.JS.Live
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ the page and you should see all of the markers still in place. Feel
|
||||||
free to try this out in separte browser tabs too!
|
free to try this out in separte browser tabs too!
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
map = Kino.Leaflet.new({51.505, -0.09}, 13)
|
map = KinoGuide.Leaflet.new({51.505, -0.09}, 13)
|
||||||
```
|
```
|
||||||
|
|
||||||
The below cell marks a random location, so you can evaluate it
|
The below cell marks a random location, so you can evaluate it
|
||||||
|
@ -207,7 +207,7 @@ multiple times for better results.
|
||||||
```elixir
|
```elixir
|
||||||
delta = fn -> (:rand.uniform() - 0.5) * 0.05 end
|
delta = fn -> (:rand.uniform() - 0.5) * 0.05 end
|
||||||
|
|
||||||
Kino.Leaflet.add_marker(map, {51.505 + delta.(), -0.09 + delta.()})
|
KinoGuide.Leaflet.add_marker(map, {51.505 + delta.(), -0.09 + delta.()})
|
||||||
```
|
```
|
||||||
|
|
||||||
We barely scratched the surface of maps, the Leaflet API alone is extremely
|
We barely scratched the surface of maps, the Leaflet API alone is extremely
|
||||||
|
@ -224,7 +224,7 @@ Let's build a counter that can be incremented both through Elixir
|
||||||
calls and client interactions.
|
calls and client interactions.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.Counter do
|
defmodule KinoGuide.Counter do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
use Kino.JS.Live
|
use Kino.JS.Live
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ to the server via `pushEvent`.
|
||||||
Let's render our counter!
|
Let's render our counter!
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
counter = Kino.Counter.new(0)
|
counter = KinoGuide.Counter.new(0)
|
||||||
```
|
```
|
||||||
|
|
||||||
As an experiment you can open another browser tab to verify
|
As an experiment you can open another browser tab to verify
|
||||||
|
@ -307,7 +307,7 @@ In addition to client events we can also use the Elixir API
|
||||||
we defined for our counter.
|
we defined for our counter.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
Kino.Counter.bump(counter)
|
KinoGuide.Counter.bump(counter)
|
||||||
```
|
```
|
||||||
|
|
||||||
In the next notebook we will get back to those concepts and
|
In the next notebook we will get back to those concepts and
|
||||||
|
|
|
@ -40,7 +40,7 @@ Smart cell that lets the user type text and generates code for printing
|
||||||
that text.
|
that text.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.Kino.PrintCell do
|
defmodule KinoGuide.PrintCell do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
use Kino.JS.Live
|
use Kino.JS.Live
|
||||||
use Kino.SmartCell, name: "Print"
|
use Kino.SmartCell, name: "Print"
|
||||||
|
@ -98,7 +98,7 @@ defmodule Kino.Kino.PrintCell do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Kino.SmartCell.register(Kino.Kino.PrintCell)
|
Kino.SmartCell.register(KinoGuide.PrintCell)
|
||||||
```
|
```
|
||||||
|
|
||||||
Most of the implementation includes regular `Kino.JS.Live` bits
|
Most of the implementation includes regular `Kino.JS.Live` bits
|
||||||
|
@ -130,7 +130,7 @@ when starting the application.
|
||||||
Now let's try out the new cell! We already inserted one below, but you
|
Now let's try out the new cell! We already inserted one below, but you
|
||||||
can add more with the <kbd>+ Smart</kbd> button.
|
can add more with the <kbd>+ Smart</kbd> button.
|
||||||
|
|
||||||
<!-- livebook:{"attrs":{"text":"something"},"kind":"Elixir.Kino.Kino.PrintCell","livebook_object":"smart_cell"} -->
|
<!-- livebook:{"attrs":{"text":"something"},"kind":"Elixir.KinoGuide.PrintCell","livebook_object":"smart_cell"} -->
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
IO.puts("something")
|
IO.puts("something")
|
||||||
|
@ -157,7 +157,7 @@ as well! To showcase this feature, let's build a cell on top of
|
||||||
`System.shell/2`.
|
`System.shell/2`.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.Kino.ShellCell do
|
defmodule KinoGuide.ShellCell do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
use Kino.JS.Live
|
use Kino.JS.Live
|
||||||
use Kino.SmartCell, name: "Shell script"
|
use Kino.SmartCell, name: "Shell script"
|
||||||
|
@ -220,7 +220,7 @@ defmodule Kino.Kino.ShellCell do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Kino.SmartCell.register(Kino.Kino.ShellCell)
|
Kino.SmartCell.register(KinoGuide.ShellCell)
|
||||||
```
|
```
|
||||||
|
|
||||||
The tuple returned from `init/2` has an optional third element that
|
The tuple returned from `init/2` has an optional third element that
|
||||||
|
@ -233,7 +233,7 @@ access it in `to_source/1`.
|
||||||
In this example we don't need any other attributes, so in the UI we
|
In this example we don't need any other attributes, so in the UI we
|
||||||
only show the cell name.
|
only show the cell name.
|
||||||
|
|
||||||
<!-- livebook:{"attrs":{"source":"echo \"There you are:\"\nls -dlh $(pwd)\nexit 1"},"kind":"Elixir.Kino.Kino.ShellCell","livebook_object":"smart_cell"} -->
|
<!-- livebook:{"attrs":{"source":"echo \"There you are:\"\nls -dlh $(pwd)\nexit 1"},"kind":"Elixir.KinoGuide.ShellCell","livebook_object":"smart_cell"} -->
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
System.shell(
|
System.shell(
|
||||||
|
@ -256,7 +256,7 @@ a Smart cell that takes JSON data and generates an Elixir code with a
|
||||||
matching data structure assigned to a user-defined variable.
|
matching data structure assigned to a user-defined variable.
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule Kino.JSONConverterCell do
|
defmodule KinoGuide.JSONConverterCell do
|
||||||
use Kino.JS
|
use Kino.JS
|
||||||
use Kino.JS.Live
|
use Kino.JS.Live
|
||||||
use Kino.SmartCell, name: "JSON converter"
|
use Kino.SmartCell, name: "JSON converter"
|
||||||
|
@ -377,7 +377,7 @@ defmodule Kino.JSONConverterCell do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Kino.SmartCell.register(Kino.JSONConverterCell)
|
Kino.SmartCell.register(KinoGuide.JSONConverterCell)
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case, one of the attributes is a variable name, so we use
|
In this case, one of the attributes is a variable name, so we use
|
||||||
|
@ -389,7 +389,7 @@ the variable name should default to `data2`.
|
||||||
This time we also added some proper styling to show a Smart cell in
|
This time we also added some proper styling to show a Smart cell in
|
||||||
its full glory!
|
its full glory!
|
||||||
|
|
||||||
<!-- livebook:{"attrs":{"json":"[\n {\n \"id\": 1,\n \"name\": \"livebook\",\n \"url\": \"https://github.com/livebook-dev/livebook\",\n \"topics\": [\n \"elixir\",\n \"visualization\",\n \"realtime\",\n \"collaborative\",\n \"notebooks\"\n ]\n },\n {\n \"id\": 2,\n \"name\": \"kino\",\n \"url\": \"https://github.com/livebook-dev/kino\",\n \"topics\": [\n \"charts\",\n \"elixir\",\n \"livebook\"\n ]\n }\n]","variable":"data"},"kind":"Elixir.Kino.JSONConverterCell","livebook_object":"smart_cell"} -->
|
<!-- livebook:{"attrs":{"json":"[\n {\n \"id\": 1,\n \"name\": \"livebook\",\n \"url\": \"https://github.com/livebook-dev/livebook\",\n \"topics\": [\n \"elixir\",\n \"visualization\",\n \"realtime\",\n \"collaborative\",\n \"notebooks\"\n ]\n },\n {\n \"id\": 2,\n \"name\": \"kino\",\n \"url\": \"https://github.com/livebook-dev/kino\",\n \"topics\": [\n \"charts\",\n \"elixir\",\n \"livebook\"\n ]\n }\n]","variable":"data"},"kind":"Elixir.KinoGuide.JSONConverterCell","livebook_object":"smart_cell"} -->
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
data = [
|
data = [
|
||||||
|
|
|
@ -206,7 +206,7 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServerTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "smart cells" do
|
describe "smart cells" do
|
||||||
defmodule Kino.SmartCell.Dumb do
|
defmodule Kino.DumbCell do
|
||||||
use GenServer
|
use GenServer
|
||||||
|
|
||||||
# Every smart cell needs a child_spec, we use the GenServer default
|
# Every smart cell needs a child_spec, we use the GenServer default
|
||||||
|
@ -238,7 +238,7 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServerTest do
|
||||||
|
|
||||||
defmodule Kino.SmartCell do
|
defmodule Kino.SmartCell do
|
||||||
def definitions() do
|
def definitions() do
|
||||||
[%{kind: "dumb", module: Kino.SmartCell.Dumb, name: "Test smart cell"}]
|
[%{kind: "dumb", module: Kino.DumbCell, name: "Test smart cell"}]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue