diff --git a/lib/live_select.ex b/lib/live_select.ex index cca59d1..dc47185 100644 --- a/lib/live_select.ex +++ b/lib/live_select.ex @@ -370,14 +370,10 @@ defmodule LiveSelect do ~S(an id to assign to the component. If none is provided, `#{form_name}_#{field}_live_select_component` will be used) attr :mode, :atom, - values: [:single, :tags], + values: [:single, :tags, :quick_tags], default: Component.default_opts()[:mode], - doc: "either `:single` (for single selection), or `:tags` (for multiple selection using tags)" - - attr :tags_mode, :atom, - values: [:default, :multiple_select], - default: Component.default_opts()[:tags_mode], - doc: "whether to use default tags mode or multi-select tags mode. Multi-select mode enables selecting multiple options without the options dropdown being hidden" + doc: + "either `:single` (for single selection), `:tags` (for multiple selection using tags), or :quick_tags (tags mode but can select multiple at a time)" attr :options, :list, doc: diff --git a/lib/live_select/component.ex b/lib/live_select/component.ex index 44cfee8..3e93c32 100644 --- a/lib/live_select/component.ex +++ b/lib/live_select/component.ex @@ -41,8 +41,7 @@ defmodule LiveSelect.Component do text_input_extra_class: nil, text_input_selected_class: nil, update_min_len: 1, - value: nil, - tags_mode: :default + value: nil ] @styles [ @@ -79,7 +78,7 @@ defmodule LiveSelect.Component do none: [] ] - @modes ~w(single tags)a + @modes ~w(single tags quick_tags)a @impl true def mount(socket) do @@ -199,11 +198,7 @@ defmodule LiveSelect.Component do &if &1.assigns.mode == :single do clear(&1, %{input_event: false, parent_event: &1.assigns[:"phx-focus"]}) else - if &1.assigns.tags_mode == :multiple_select do - &1 - else - parent_event(&1, &1.assigns[:"phx-focus"], %{id: &1.assigns.id}) - end + parent_event(&1, &1.assigns[:"phx-focus"], %{id: &1.assigns.id}) end ) |> assign(hide_dropdown: false) @@ -441,36 +436,39 @@ defmodule LiveSelect.Component do option = Enum.at(socket.assigns.options, active_option) if already_selected?(option, selection) do - pos = selection_index(option, selection) + pos = get_selection_index(option, selection) unselect(socket, pos) else select(socket, Enum.at(socket.assigns.options, socket.assigns.active_option), extra_params) end end - defp selection_index(option, selection) do - Enum.find_index(selection, fn %{label: label} -> label == option.label end) - end - defp maybe_select(socket, extra_params) do select(socket, Enum.at(socket.assigns.options, socket.assigns.active_option), extra_params) end + defp get_selection_index(option, selection) do + Enum.find_index(selection, fn %{label: label} -> label == option.label end) + end + defp select(socket, selected, extra_params) do selection = case socket.assigns.mode do :tags -> socket.assigns.selection ++ [selected] + :quick_tags -> + socket.assigns.selection ++ [selected] + _ -> [selected] end socket |> assign( - active_option: if(multi_select_mode?(socket), do: socket.assigns.active_option, else: -1), + active_option: if(quick_tags_mode?(socket), do: socket.assigns.active_option, else: -1), selection: selection, - hide_dropdown: not multi_select_mode?(socket) + hide_dropdown: not quick_tags_mode?(socket) ) |> maybe_save_selection() |> client_select(Map.merge(%{input_event: true}, extra_params)) @@ -544,7 +542,7 @@ defmodule LiveSelect.Component do List.wrap(normalize_selection_value(value, options ++ current_selection, value_mapper)) end - defp update_selection(value, current_selection, options, :tags, value_mapper) do + defp update_selection(value, current_selection, options, _mode, value_mapper) do value = if Enumerable.impl_for(value), do: value, else: [value] Enum.map(value, &normalize_selection_value(&1, options ++ current_selection, value_mapper)) @@ -695,8 +693,8 @@ defmodule LiveSelect.Component do Enum.any?(selection, fn item -> item.label == option.label end) end - defp multi_select_mode?(socket) do - socket.assigns.mode == :tags && socket.assigns.tags_mode == :multiple_select + defp quick_tags_mode?(socket) do + socket.assigns.mode == :quick_tags end defp next_selectable(%{ @@ -711,7 +709,7 @@ defmodule LiveSelect.Component do options: options, active_option: active_option, selection: selection, - tags_mode: :multiple_select + mode: :quick_tags }) do options |> Enum.with_index() @@ -740,7 +738,7 @@ defmodule LiveSelect.Component do options: options, active_option: active_option, selection: selection, - tags_mode: :multiple_select + mode: :quick_tags }) do options |> Enum.with_index() diff --git a/lib/live_select/component.html.heex b/lib/live_select/component.html.heex index d0841c7..a55681a 100644 --- a/lib/live_select/component.html.heex +++ b/lib/live_select/component.html.heex @@ -8,10 +8,11 @@ data-field={@field.id} data-debounce={@debounce} > - <%= if @mode == :tags && Enum.any?(@selection) do %> +
ølksdjf
<.live_component module={LiveComponentForm} id="lc_form" /> """ end diff --git a/lib/support/live_select_web/live/showcase_live.ex b/lib/support/live_select_web/live/showcase_live.ex index a4dc611..2ccc710 100644 --- a/lib/support/live_select_web/live/showcase_live.ex +++ b/lib/support/live_select_web/live/showcase_live.ex @@ -67,10 +67,15 @@ defmodule LiveSelectWeb.ShowcaseLive do field(:allow_clear, :boolean) field(:debounce, :integer, default: Component.default_opts()[:debounce]) field(:disabled, :boolean) + field(:custom_option_html, :boolean) field(:max_selectable, :integer, default: Component.default_opts()[:max_selectable]) field(:user_defined_options, :boolean) - field(:mode, Ecto.Enum, values: [:single, :tags], default: Component.default_opts()[:mode]) - field(:tags_mode, Ecto.Enum, values: [:default, :multiple_select], default: Component.default_opts()[:tags_mode]) + + field(:mode, Ecto.Enum, + values: [:single, :tags, :quick_tags], + default: Component.default_opts()[:mode] + ) + field(:new, :boolean, default: true) field(:placeholder, :string, default: "Search for a city") field(:search_delay, :integer, default: 10) @@ -94,10 +99,10 @@ defmodule LiveSelectWeb.ShowcaseLive do :allow_clear, :debounce, :disabled, + :custom_option_html, :max_selectable, :user_defined_options, :mode, - :tags_mode, :options, :selection, :placeholder, @@ -121,7 +126,7 @@ defmodule LiveSelectWeb.ShowcaseLive do default_opts = Component.default_opts() settings - |> Map.drop([:search_delay, :new, :selection]) + |> Map.drop([:search_delay, :new, :selection, :custom_option_html]) |> Map.from_struct() |> then( &if is_nil(&1.style) do @@ -140,8 +145,12 @@ defmodule LiveSelectWeb.ShowcaseLive do end defp maybe_set_classes_for_multiselect(opts) do - if LiveSelectWeb.ShowcaseLive.multiple_select?(opts) |> dbg do - Keyword.put(opts, :selected_option_class, "cursor-pointer font-bold hover:bg-gray-400 rounded") + if LiveSelectWeb.ShowcaseLive.quick_tags?(opts[:mode]) do + Keyword.put( + opts, + :selected_option_class, + "cursor-pointer font-bold hover:bg-gray-400 rounded" + ) else opts end @@ -250,20 +259,55 @@ defmodule LiveSelectWeb.ShowcaseLive do assigns = assign(assigns, opts: opts, format_value: format_value) ~H""" -