mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-03-06 11:53:44 +08:00
Added input select (#448)
* Added range input (Slider)
* Added range input (Slider)
* Custom css to range input
* Formatting correction
* Defined min and max values of input range
* Revert "Defined min and max values of input range"
This reverts commit 815167ab0f
.
* Added input select
* working with a options like list
* Formatting correction
* swapped li for inputs in input settings
* Removed unused attribute
* Final adjustments
Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com>
This commit is contained in:
parent
aa95d81729
commit
ad999cf9c0
4 changed files with 99 additions and 3 deletions
|
@ -100,6 +100,10 @@
|
|||
@apply appearance-none border-transparent bg-blue-600 hover:bg-blue-700 cursor-pointer rounded-xl;
|
||||
}
|
||||
|
||||
.input-select {
|
||||
@apply w-60;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
@apply mb-0.5 text-sm text-gray-800 font-medium;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ defmodule Livebook.Notebook.Cell.Input do
|
|||
props: props()
|
||||
}
|
||||
|
||||
@type type :: :text | :url | :number | :password | :textarea | :color | :range
|
||||
@type type :: :text | :url | :number | :password | :textarea | :color | :range | :select
|
||||
|
||||
@typedoc """
|
||||
Additional properties adjusting the given input type.
|
||||
|
@ -97,6 +97,7 @@ defmodule Livebook.Notebook.Cell.Input do
|
|||
def default_props(type)
|
||||
|
||||
def default_props(:range), do: %{min: 0, max: 100, step: 1}
|
||||
def default_props(:select), do: %{options: [""]}
|
||||
def default_props(_type), do: %{}
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -159,6 +159,26 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
"""
|
||||
end
|
||||
|
||||
defp cell_input(%{cell_view: %{input_type: :select}} = assigns) do
|
||||
~H"""
|
||||
<div class="flex items-center space-x-2">
|
||||
<select
|
||||
data-element="input"
|
||||
spellcheck="false"
|
||||
phx-debounce="300"
|
||||
class="input input-select"
|
||||
tabindex="-1"
|
||||
name="value">
|
||||
<%= for option <- @cell_view.props.options do %>
|
||||
<option value={option} selected={option == @cell_view.value}>
|
||||
<%= option %>
|
||||
</option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp cell_input(assigns) do
|
||||
~H"""
|
||||
<input type={html_input_type(@cell_view.input_type)}
|
||||
|
@ -177,6 +197,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|
|||
defp html_input_type(:number), do: "number"
|
||||
defp html_input_type(:color), do: "color"
|
||||
defp html_input_type(:range), do: "range"
|
||||
defp html_input_type(:select), do: "select"
|
||||
defp html_input_type(_), do: "text"
|
||||
|
||||
defp cell_body(assigns) do
|
||||
|
|
|
@ -42,7 +42,7 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
<div class="input-label">Name</div>
|
||||
<input type="text" class="input" name="attrs[name]" value={@attrs.name} autofocus />
|
||||
</div>
|
||||
<.extra_fields type={@attrs.type} props={@attrs.props} />
|
||||
<.extra_fields type={@attrs.type} props={@attrs.props} myself={@myself} />
|
||||
<.switch_checkbox
|
||||
name="attrs[reactive]"
|
||||
label="Reactive (reevaluates dependent cells on change)"
|
||||
|
@ -78,6 +78,46 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
"""
|
||||
end
|
||||
|
||||
defp extra_fields(%{type: :select} = assigns) do
|
||||
~H"""
|
||||
<div class="flex flex-col">
|
||||
<div class="input-label mb-0">Options</div>
|
||||
<div class="my-2 flex flex-col space-y-2">
|
||||
<%= for {option, idx} <- Enum.with_index(@props.options) do %>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="text"
|
||||
class="input"
|
||||
name="attrs[props][options][]"
|
||||
value={option} />
|
||||
<button
|
||||
class="button button-gray button-square-icon"
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
phx-target={@myself}
|
||||
phx-click="select_options_action"
|
||||
phx-value-action="delete"
|
||||
phx-value-index={idx}
|
||||
disabled={length(@props.options) == 1}>
|
||||
<.remix_icon icon="delete-bin-6-line" />
|
||||
</button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="button button-outlined-gray"
|
||||
type="button"
|
||||
phx-target={@myself}
|
||||
phx-click="select_options_action"
|
||||
phx-value-action="add">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp extra_fields(assigns), do: ~H""
|
||||
|
||||
@impl true
|
||||
|
@ -100,6 +140,24 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
|
||||
end
|
||||
|
||||
def handle_event("select_options_action", params, socket) do
|
||||
{action, params} = Map.pop!(params, "action")
|
||||
attrs = socket.assigns.attrs
|
||||
options = select_options_action(action, params, attrs.props.options)
|
||||
attrs = put_in(attrs.props.options, options)
|
||||
valid? = valid_options?(options)
|
||||
{:noreply, socket |> assign(attrs: attrs) |> assign(valid: valid?)}
|
||||
end
|
||||
|
||||
defp select_options_action("add", _params, options) do
|
||||
options ++ [""]
|
||||
end
|
||||
|
||||
defp select_options_action("delete", %{"index" => index}, options) do
|
||||
index = String.to_integer(index)
|
||||
List.delete_at(options, index)
|
||||
end
|
||||
|
||||
defp validate_attrs(data, prev_attrs) do
|
||||
name = data["name"]
|
||||
type = data["type"] |> String.to_existing_atom()
|
||||
|
@ -126,10 +184,20 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
{valid?, data}
|
||||
end
|
||||
|
||||
defp validate_props(data, :select) do
|
||||
options = data["options"] || []
|
||||
valid? = valid_options?(options)
|
||||
{valid?, %{options: options}}
|
||||
end
|
||||
|
||||
defp validate_props(_data, _type) do
|
||||
{true, %{}}
|
||||
end
|
||||
|
||||
defp valid_options?(options) do
|
||||
options != [] and options == Enum.uniq(options)
|
||||
end
|
||||
|
||||
defp parse_number(string) do
|
||||
case Float.parse(string) do
|
||||
{number, _} ->
|
||||
|
@ -143,6 +211,7 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
|
||||
defp default_value(:color, _props), do: "#3E64FF"
|
||||
defp default_value(:range, %{min: min}), do: to_string(min)
|
||||
defp default_value(:select, %{options: [option | _]}), do: option
|
||||
defp default_value(_type, _props), do: ""
|
||||
|
||||
defp input_types do
|
||||
|
@ -153,7 +222,8 @@ defmodule LivebookWeb.SessionLive.InputCellSettingsComponent do
|
|||
text: "Text",
|
||||
textarea: "Textarea",
|
||||
url: "URL",
|
||||
range: "Range"
|
||||
range: "Range",
|
||||
select: "Select"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue