Media selector modal component.
A reusable modal component for selecting media files from anywhere in the admin panel. Supports both single and multiple selection modes.
Usage
# In parent LiveView, add to socket assigns
socket
|> assign(:show_media_selector, false)
|> assign(:media_selection_mode, :single)
|> assign(:media_selected_uuids, [])
# In template (IMPORTANT: Must pass phoenix_kit_current_user for uploads to work)
<.live_component
module={PhoenixKitWeb.Live.Components.MediaSelectorModal}
id="media-selector-modal"
show={@show_media_selector}
mode={@media_selection_mode}
selected_uuids={@media_selected_uuids}
phoenix_kit_current_user={@phoenix_kit_current_user}
/>
# To open the modal
def handle_event("open_media_selector", _params, socket) do
{:noreply, assign(socket, :show_media_selector, true)}
end
# To receive selected media
def handle_info({:media_selected, file_uuids}, socket) do
# Handle the selected file UUIDs
{:noreply, socket |> assign(:gallery_uuids, file_uuids)}
endRequired host wiring (do not skip — silent failure otherwise)
This is a LiveComponent, so it has no handle_info of its own; it
reports the user's choice by sending a process message to the host
LiveView. The host MUST handle it, or the selection is silently
dropped (the modal closes, nothing happens — no crash, no warning):
handle_info({:media_selected, file_uuids}, socket)— required. Fired when the user confirms;file_uuidsis the chosen list.handle_info({:media_selector_closed}, socket)— recommended (fired on cancel/close) so the host can reset its own open-state assign.
Each host does something different with the files (avatar, gallery,
product images…), so there is intentionally no use ...Embed macro to
inject this — the handling is yours to write.
Alternative — :notify: pass notify: {SomeComponent, id} and the
result is delivered to that component via send_update instead
(update(%{media_selected: uuids}, socket) /
update(%{media_selector_closed: true}, socket)), for when the
consumer is itself a LiveComponent.
Attrs
show— boolean, controls modal visibilitymode—:singleor:multipleselected_uuids— list of already-selected file UUIDsphoenix_kit_current_user— required for uploads to attribute the filefile_type_filter—:all(default),:image,:video, or:audio. Filters the library grid AND gates uploads (server-side, not just the clientacceptlist).lock_file_type—false(default) treatsfile_type_filteras a starting point the user can change;truemakes it a constraint: the type<select>is hidden and the change event is refused. Use it whenever the selection fills a typed field — an audio slot, an image slot — so the user can't pick something the consumer will only reject afterwards.title— heading for the modal. Pass the picker's purpose ("Select Featured Image", "Select Avatar") so the user knows what they are choosing FOR. nil (default) derives a type-aware fallback: a locked image picker titles itself "Select Image" (or "Select Images" in:multiplemode); everything else stays "Select Media".always_show_search—false(default) lets the search/filter row hide itself when it could do nothing: a locked picker browsing without a query shows it only once the library holds 10+ files (below that everything fits on one screen).trueforces the row to always render.browse—true(default) shows the library grid + search + type filter;falseis upload-only (dropzone + Confirm; uploaded files auto-select)user_uuid— when set, restricts the library to files owned by that user; nil (default) shows the full libraryscope_folder_id— when set, restricts both the browse query and the post-upload home folder to this folder UUID. Plugins scoping the picker to a single domain object (e.g. a catalogue item) pass this after lazy-creating their folder; files already living elsewhere get aFolderLinkinto the scope folder on re-upload rather than being moved out from under their original owner.nil(default) = no scope, legacy full-library behaviour.
Summary
Functions
Callback implementation for Phoenix.LiveComponent.handle_event/3.
Callback implementation for Phoenix.LiveComponent.render/1.
Callback implementation for Phoenix.LiveComponent.update/2.
Functions
Callback implementation for Phoenix.LiveComponent.handle_event/3.
Callback implementation for Phoenix.LiveComponent.render/1.
Callback implementation for Phoenix.LiveComponent.update/2.