KinoLiveComponent を使って Livebook 上でコンポーネントを実装、表示する

## はじめに

Phoenix LievView ではコンポーネント（部品）を作り、 Web UI に組み込んで使用します

https://github.com/phoenixframework/phoenix_live_view

KinoLiveComponent を使うと、 Livebook 上でコンポーネントを実装し UI を表示できます

https://github.com/anthonyshull/kino_live_component

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/kino/kino_live_component.livemd

## 事前準備

KinoLiveComponent を使うためには、 Livebook とは別に Phoenix アプリケーションを起動している必要があります

KinoLiveComponent を使うということは、 Phoenix LiveView の Web UI を実装しようとしているはずです

その実装中のアプリケーションにも開発用に KinoLiveComponent を依存モジュールとして追加します

"mix.exs" の deps に `{:kino_live_component, ">= 0.0.0", only: :dev}` を追加しましょう

```elixir
...
  defp deps do
    [
      ...,
      {:kino_live_component, ">= 0.0.0", only: :dev}
    ]
  end
...
```

追加したら `mix deps.get` でインストールしておきます

"lib/..._web/router.ex" に Livebook からアクセスするためのルートを用意しておきます

```elixir
  import KinoLiveComponent.Plug, only: [allow_insecure_connection: 2]
...
  if Mix.env() == :dev do
    scope "/kino-live-component", KinoLiveComponent do
      pipe_through([:allow_insecure_connection])

      live("/", Live.Index)
    end
  end
...
```


また、 "config/dev.exs" で開発用に使っているポート番号（デフォルトでは 4000）を確認しましょう

```elixir
config :elixir_mobile, ...Web.Endpoint,
  # Binding to loopback ipv4 address prevents access from other machines.
  # Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
  http: [ip: {127, 0, 0, 1}, port: 4000],
  ...
```

この状態で `mix phx.server` を実行し、アプリケーションを起動しておきます

特に今作ろうとしているアプリケーションがない、とりあえず試したいだけ、という場合は KinoLiveComponent 自体を Phoenix アプリケーションとして使用します

具体的には以下のコマンドを実行してください

```bash
git clone git@github.com:anthonyshull/kino_live_component.git
cd kino_live_component
mix deps.get
iex --sname kino-live-component --cookie foobarbaz -S mix phx.server
```

Phoenix が `9999` ポートで起動します

## セットアップ

Livebook で新しいノートブックを開き、セットアップセルで KinoLiveComponent をインストールします

このとき、 KinoLiveComponent の接続先を `config` で指定します

`KinoLiveComponent` 自体を接続先にしている場合、ローカルホストの `9999` ポートで起動しており、パスは `/kino-live-component` でルーティングしているため、 `endpoint` には `http://localhost:9999/kino-live-component` を指定することになります

```elixir
Mix.install(
  [
    {:kino_live_component, "~> 0.0.3"}
  ],
  config: [
    kino_live_component: [
      endpoint: "http://localhost:9999/kino-live-component"
    ]
  ]
)
```

## Phoenix.Component

Livebook のセルでコンポーネントを実装してみます

`~H` のシギルをインポートして簡単なラベルを作ってみましょう

```elixir
import Phoenix.Component, only: [sigil_H: 2]

assigns = %{
  content: "Hello, Phoenix component!"
}

~H"""
<div class="p-3 bg-orange-500 text-white rounded-xl cursor-pointer">
  <%= @content %>
</div>
"""
|> KinoLiveComponent.component()
```

実行結果

![スクリーンショット 2024-11-15 8.29.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/390d2d2b-0e60-d0d5-5332-ec096ceced23.png)

コンポーネントが表示されました

TailwindCSS もちゃんと効いているし、 `assigns` に入れた `content` も表示されています

## Phoenix.LiveComponent

もちろん、 LiveComponent も実装できます

https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html

```elixir
defmodule MyLiveComponent do
  use Phoenix.LiveComponent

  def render(assigns) do
    ~H"""
    <div class="p-3 bg-red-200 text-black rounded-lg">
      <%= @content %>
    </div>
    """
  end
end

assigns = %{
  content: "Hello, Phoenix live component!"
}

KinoLiveComponent.component(MyLiveComponent, assigns)
```

実行結果

![スクリーンショット 2024-11-15 8.35.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/53475074-2323-9689-645c-952e8c53a847.png)

## まとめ

Livebook 上でコンポーネントを実装し、表示することができました

試行錯誤しながら UI を作るときに使えそうですね