mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-03-14 00:36:41 +08:00
Add :debounce to input outputs when missing (#2228)
This commit is contained in:
parent
edc09cd386
commit
05418db0c6
6 changed files with 75 additions and 22 deletions
|
@ -298,28 +298,33 @@ defprotocol Livebook.Runtime do
|
|||
%{
|
||||
type: :text,
|
||||
default: String.t(),
|
||||
label: String.t()
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer()
|
||||
}
|
||||
| %{
|
||||
type: :textarea,
|
||||
default: String.t(),
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer(),
|
||||
monospace: boolean()
|
||||
}
|
||||
| %{
|
||||
type: :password,
|
||||
default: String.t(),
|
||||
label: String.t()
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer()
|
||||
}
|
||||
| %{
|
||||
type: :number,
|
||||
default: number() | nil,
|
||||
label: String.t()
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer()
|
||||
}
|
||||
| %{
|
||||
type: :url,
|
||||
default: String.t() | nil,
|
||||
label: String.t()
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer()
|
||||
}
|
||||
| %{
|
||||
type: :select,
|
||||
|
@ -336,6 +341,7 @@ defprotocol Livebook.Runtime do
|
|||
type: :range,
|
||||
default: number(),
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer(),
|
||||
min: number(),
|
||||
max: number(),
|
||||
step: number()
|
||||
|
@ -364,7 +370,8 @@ defprotocol Livebook.Runtime do
|
|||
| %{
|
||||
type: :color,
|
||||
default: String.t(),
|
||||
label: String.t()
|
||||
label: String.t(),
|
||||
debounce: :blur | non_neg_integer()
|
||||
}
|
||||
| %{
|
||||
type: :image,
|
||||
|
|
|
@ -2886,39 +2886,70 @@ defmodule Livebook.Session do
|
|||
end
|
||||
end
|
||||
|
||||
# Maps legacy outputs and adds missing attributes
|
||||
# Normalizes output to match the most recent specification.
|
||||
#
|
||||
# Rewrites legacy output formats and adds defaults for newly introduced
|
||||
# attributes that are missing.
|
||||
defp normalize_runtime_output(output)
|
||||
|
||||
defp normalize_runtime_output(%{type: :input, attrs: attrs} = output)
|
||||
when attrs.type in [:text, :textarea, :password, :number, :url, :range, :color] and
|
||||
not is_map_key(attrs, :debounce) do
|
||||
put_in(output.attrs[:debounce], :blur)
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
# Traverse composite outputs
|
||||
|
||||
defp normalize_runtime_output(output) when output.type in [:frame, :tabs, :grid] do
|
||||
outputs = Enum.map(output.outputs, &normalize_runtime_output/1)
|
||||
%{output | outputs: outputs}
|
||||
end
|
||||
|
||||
defp normalize_runtime_output(%{type: :frame_update} = output) do
|
||||
{update_type, new_outputs} = output.update
|
||||
new_outputs = Enum.map(new_outputs, &normalize_runtime_output/1)
|
||||
%{output | update: {update_type, new_outputs}}
|
||||
end
|
||||
|
||||
defp normalize_runtime_output(output) when is_map(output), do: output
|
||||
|
||||
# Rewrite tuples to maps for backward compatibility with Kino <= 0.10.0
|
||||
|
||||
defp normalize_runtime_output(:ignored) do
|
||||
%{type: :ignored}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
# Rewrite tuples to maps for backward compatibility with Kino <= 0.10.0
|
||||
defp normalize_runtime_output({:text, text}) do
|
||||
%{type: :terminal_text, text: text, chunk: false}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:plain_text, text}) do
|
||||
%{type: :plain_text, text: text, chunk: false}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:markdown, text}) do
|
||||
%{type: :markdown, text: text, chunk: false}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:image, content, mime_type}) do
|
||||
%{type: :image, content: content, mime_type: mime_type}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
# Rewrite older output format for backward compatibility with Kino <= 0.5.2
|
||||
defp normalize_runtime_output({:js, %{ref: ref, pid: pid, assets: assets, export: export}}) do
|
||||
normalize_runtime_output(
|
||||
{:js, %{js_view: %{ref: ref, pid: pid, assets: assets}, export: export}}
|
||||
)
|
||||
{:js, %{js_view: %{ref: ref, pid: pid, assets: assets}, export: export}}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:js, info}) do
|
||||
%{type: :js, js_view: info.js_view, export: info.export}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :default} = info}) do
|
||||
|
@ -2928,6 +2959,7 @@ defmodule Livebook.Session do
|
|||
outputs: Enum.map(outputs, &normalize_runtime_output/1),
|
||||
placeholder: Map.get(info, :placeholder, true)
|
||||
}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :replace}}) do
|
||||
|
@ -2936,6 +2968,7 @@ defmodule Livebook.Session do
|
|||
ref: ref,
|
||||
update: {:replace, Enum.map(outputs, &normalize_runtime_output/1)}
|
||||
}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :append}}) do
|
||||
|
@ -2944,10 +2977,12 @@ defmodule Livebook.Session do
|
|||
ref: ref,
|
||||
update: {:append, Enum.map(outputs, &normalize_runtime_output/1)}
|
||||
}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:tabs, outputs, %{labels: labels}}) do
|
||||
%{type: :tabs, outputs: Enum.map(outputs, &normalize_runtime_output/1), labels: labels}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:grid, outputs, info}) do
|
||||
|
@ -2958,6 +2993,7 @@ defmodule Livebook.Session do
|
|||
gap: Map.get(info, :gap, 8),
|
||||
boxed: Map.get(info, :boxed, false)
|
||||
}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:input, attrs}) do
|
||||
|
@ -2970,6 +3006,7 @@ defmodule Livebook.Session do
|
|||
end
|
||||
|
||||
Map.merge(fields, %{type: :input, attrs: attrs})
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:control, attrs}) do
|
||||
|
@ -2992,6 +3029,7 @@ defmodule Livebook.Session do
|
|||
end
|
||||
|
||||
Map.merge(fields, %{type: :control, attrs: attrs})
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output({:error, message, type}) do
|
||||
|
@ -3002,9 +3040,11 @@ defmodule Livebook.Session do
|
|||
end
|
||||
|
||||
%{type: :error, message: message, context: context}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
|
||||
defp normalize_runtime_output(other) do
|
||||
%{type: :unknown, output: other}
|
||||
|> normalize_runtime_output()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -169,7 +169,7 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
class="input-range"
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce={@attrs[:debounce] || "blur"}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
|
@ -190,7 +190,7 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
class={["input min-h-[38px] max-h-[300px] tiny-scrollbar", @attrs.monospace && "font-mono"]}
|
||||
name="html_value"
|
||||
phx-hook="TextareaAutosize"
|
||||
phx-debounce={@attrs[:debounce] || "blur"}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
><%= [?\n, @value] %></textarea>
|
||||
|
@ -206,7 +206,7 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
class="input w-auto bg-gray-50"
|
||||
name="html_value"
|
||||
value={@value}
|
||||
phx-debounce={@attrs[:debounce] || "blur"}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
|
@ -241,7 +241,7 @@ defmodule LivebookWeb.Output.InputComponent do
|
|||
class="input w-auto invalid:input--error"
|
||||
name="html_value"
|
||||
value={to_string(@value)}
|
||||
phx-debounce={@attrs[:debounce] || "blur"}
|
||||
phx-debounce={@attrs.debounce}
|
||||
phx-target={@myself}
|
||||
spellcheck="false"
|
||||
autocomplete="off"
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Livebook.Session.DataTest do
|
|||
ref: "ref1",
|
||||
id: "i1",
|
||||
destination: nil,
|
||||
attrs: %{type: :text, default: "hey", label: "Text"}
|
||||
attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
|
||||
}
|
||||
|
||||
defp eval_meta(opts \\ []) do
|
||||
|
@ -4510,7 +4510,7 @@ defmodule Livebook.Session.DataTest do
|
|||
ref: "ref1",
|
||||
id: "i1",
|
||||
destination: nil,
|
||||
attrs: %{type: :text, default: "hey", label: "Text"}
|
||||
attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
|
||||
}
|
||||
|
||||
input2 = %{
|
||||
|
@ -4518,7 +4518,7 @@ defmodule Livebook.Session.DataTest do
|
|||
ref: "ref2",
|
||||
id: "i2",
|
||||
destination: nil,
|
||||
attrs: %{type: :text, default: "hey", label: "Text"}
|
||||
attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
|
||||
}
|
||||
|
||||
data =
|
||||
|
|
|
@ -219,7 +219,7 @@ defmodule Livebook.SessionTest do
|
|||
ref: "ref",
|
||||
id: "input1",
|
||||
destination: :noop,
|
||||
attrs: %{type: :text, default: "hey", label: "Name"}
|
||||
attrs: %{type: :text, default: "hey", label: "Name", debounce: :blur}
|
||||
}
|
||||
|
||||
smart_cell = %{
|
||||
|
@ -1899,7 +1899,7 @@ defmodule Livebook.SessionTest do
|
|||
ref: "ref",
|
||||
id: "input1",
|
||||
destination: :noop,
|
||||
attrs: %{type: :text, default: "hey", label: "Name"}
|
||||
attrs: %{type: :text, default: "hey", label: "Name", debounce: :blur}
|
||||
}
|
||||
|
||||
send(session.pid, {:runtime_evaluation_output, cell_id, legacy_output})
|
||||
|
|
|
@ -518,7 +518,13 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
ref: "ref1",
|
||||
id: "input1",
|
||||
destination: test,
|
||||
attrs: %{type: :textarea, default: "hey", label: "Name", monospace: false}
|
||||
attrs: %{
|
||||
type: :textarea,
|
||||
default: "hey",
|
||||
label: "Name",
|
||||
debounce: :blur,
|
||||
monospace: false
|
||||
}
|
||||
}
|
||||
|
||||
Session.subscribe(session.id)
|
||||
|
@ -552,7 +558,7 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
ref: "input_ref1",
|
||||
id: "input1",
|
||||
destination: test,
|
||||
attrs: %{type: :text, default: "initial", label: "Name"}
|
||||
attrs: %{type: :text, default: "initial", label: "Name", debounce: :blur}
|
||||
}
|
||||
],
|
||||
submit: "Send",
|
||||
|
@ -781,7 +787,7 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
ref: "ref1",
|
||||
id: "input1",
|
||||
destination: test,
|
||||
attrs: %{type: :number, default: 1, label: "Input inside frame"}
|
||||
attrs: %{type: :number, default: 1, label: "Input inside frame", debounce: :blur}
|
||||
}
|
||||
|
||||
frame_update = %{
|
||||
|
|
Loading…
Reference in a new issue