diff --git a/assets/vega_lite/main.js b/assets/vega_lite/main.js index 6f3449a..0bed33a 100644 --- a/assets/vega_lite/main.js +++ b/assets/vega_lite/main.js @@ -129,7 +129,12 @@ export function init(ctx, data) { let theme = config.theme === "livebook" ? livebookTheme : {}; const options = { - actions: { export: true, source: false, compiled: false, editor: false }, + actions: { + export: config.export, + source: config.view_source, + compiled: config.view_compiled_vega, + editor: config.open_vega_editor + }, config: theme, }; diff --git a/lib/kino/vega_lite.ex b/lib/kino/vega_lite.ex index 28ab569..5970eb1 100644 --- a/lib/kino/vega_lite.ex +++ b/lib/kino/vega_lite.ex @@ -52,6 +52,14 @@ defmodule Kino.VegaLite do ) end + @default_config [ + theme: :livebook, + export: true, + view_source: true, + view_compiled_vega: false, + open_vega_editor: true + ] + @doc """ Applies global configuration options for the VegaLite kinos. @@ -60,19 +68,42 @@ defmodule Kino.VegaLite do * `:theme` - the theme to be applied on the rendered VegaLite charts. Currently the only supported theme is `:livebook`. If set to `nil`, no theme is applied. Defaults to `:livebook`. + + * `:export` - whether the **Export as SVG/PNG** actions will be + enabled on the chart widget. Defaults to `true`. + + * `:view_source` - whether the **View Source** action will be enabled + on the chart widget. Defaults to `true`. + + * `:view_compiled_vega` - whether the **View Compiled Vega** action + will be enabled on the chart widget. Defaults to `false`. + + * `:open_vega_editor` - whether the **Open in Vega Editor** action + will be enabled on the chart widget. Defaults to `true`. """ @spec configure(keyword()) :: :ok def configure(opts) do - opts = Keyword.validate!(opts, theme: :livebook) + opts = Keyword.validate!(opts, @default_config) unless opts[:theme] in [nil, :livebook] do raise ArgumentError, "expected :theme to be either :livebook or nil, got: #{inspect(opts[:theme])}" end + for field <- [:export, :view_source, :view_compiled_vega, :open_vega_editor] do + validate_boolean!(opts, field) + end + Application.put_all_env(kino_vega_lite: opts) end + defp validate_boolean!(opts, field) do + unless is_boolean(opts[field]) do + raise ArgumentError, + "expected #{inspect(field)} to be a boolean, got: #{inspect(opts[field])}" + end + end + @doc """ Renders and returns a new kino with the given VegaLite definition. @@ -256,9 +287,7 @@ defmodule Kino.VegaLite do end defp config do - default_config = [theme: :livebook] - - default_config + @default_config |> Keyword.merge(Application.get_all_env(:kino_vega_lite)) |> Map.new() end diff --git a/test/kino/vega_lite_test.exs b/test/kino/vega_lite_test.exs index 62da2bf..8f1e354 100644 --- a/test/kino/vega_lite_test.exs +++ b/test/kino/vega_lite_test.exs @@ -99,19 +99,49 @@ defmodule Kino.VegaLiteTest do "expected :theme to be either :livebook or nil, got: :invalid", fn -> Kino.VegaLite.configure(theme: :invalid) end - # with default theme + # with invalid value for boolean options + for field <- [:export, :view_source, :view_compiled_vega, :open_vega_editor] do + message = "expected #{inspect(field)} to be a boolean, got: nil" + assert_raise ArgumentError, message, fn -> Kino.VegaLite.configure([{field, nil}]) end + end + + # with default values kino = start_kino() data = connect(kino) - assert %{config: %{theme: :livebook}} = data - # with empty theme - Kino.VegaLite.configure(theme: nil) + assert %{ + config: %{ + theme: :livebook, + export: true, + view_source: true, + view_compiled_vega: false, + open_vega_editor: true + } + } = data + + # with updated config + Kino.VegaLite.configure( + theme: nil, + export: false, + view_source: false, + view_compiled_vega: true, + open_vega_editor: false + ) kino = start_kino() data = connect(kino) - assert %{config: %{theme: nil}} = data + + assert %{ + config: %{ + theme: nil, + export: false, + view_source: false, + view_compiled_vega: true, + open_vega_editor: false + } + } = data end defp start_kino() do