diff --git a/assets/js/phoenix_live_view/hooks.js b/assets/js/phoenix_live_view/hooks.js
index 672f8cea86..1e95244027 100644
--- a/assets/js/phoenix_live_view/hooks.js
+++ b/assets/js/phoenix_live_view/hooks.js
@@ -43,6 +43,21 @@ let Hooks = {
URL.revokeObjectURL(this.url)
}
},
+ // Currently this is exactly the same as the LiveImgPreview, but I wanted to add this
+ // so possibly this can have functionality specific to videos in the future.
+ LiveVideoPreview: {
+ mounted(){
+ this.ref = this.el.getAttribute("data-phx-entry-ref")
+ this.inputEl = document.getElementById(this.el.getAttribute(PHX_UPLOAD_REF))
+ LiveUploader.getEntryDataURL(this.inputEl, this.ref, url => {
+ this.url = url
+ this.el.src = url
+ })
+ },
+ destroyed(){
+ URL.revokeObjectURL(this.url)
+ }
+ },
FocusWrap: {
mounted(){
this.focusStart = this.el.firstElementChild
diff --git a/lib/phoenix_component.ex b/lib/phoenix_component.ex
index 1e3f7fc918..163d251f73 100644
--- a/lib/phoenix_component.ex
+++ b/lib/phoenix_component.ex
@@ -2582,6 +2582,46 @@ defmodule Phoenix.Component do
raise ArgumentError, "missing required :entry attribute to <.live_img_preview/>"
end
+ @doc """
+ Generates a video preview on the client for a selected file.
+
+ ## Examples
+
+ ```heex
+ <%= for entry <- @uploads.avatar.entries do %>
+ <.live_video_preview entry={entry} width="400" />
+ <% end %>
+ ```
+ """
+ @doc type: :component
+ def live_video_preview(assigns)
+
+ # attr :entry, Phoenix.LiveView.UploadEntry, required: true
+ # attr :rest, :global
+ def live_video_preview(%{entry: %Phoenix.LiveView.UploadEntry{ref: ref} = entry} = assigns) do
+ rest =
+ assigns
+ |> assigns_to_attributes([:entry])
+ |> Keyword.put_new_lazy(:id, fn -> "phx-preview-#{ref}" end)
+
+ assigns = assign(assigns, entry: entry, ref: ref, rest: rest)
+
+ ~H"""
+
+ """
+ end
+
+ def live_video_preview(_assigns) do
+ raise ArgumentError, "missing required :entry attribute to <.live_video_preview/>"
+ end
+
@doc """
Intersperses separator slot between an enumerable.
diff --git a/test/phoenix_component/components_test.exs b/test/phoenix_component/components_test.exs
index 72b2ae6958..6a2d07590d 100644
--- a/test/phoenix_component/components_test.exs
+++ b/test/phoenix_component/components_test.exs
@@ -479,6 +479,70 @@ defmodule Phoenix.LiveView.ComponentsTest do
end
end
+ describe "live_img_preview/1" do
+ test "basic usage" do
+ entry = %Phoenix.LiveView.UploadEntry{
+ progress: 100,
+ preflighted?: true,
+ upload_config: :poster_imgix_src,
+ upload_ref: "phx-Fz1Xjn4seffww0vC",
+ ref: "1",
+ uuid: "898e29b9-1724-4b5f-b42f-2389b85bb9f4",
+ valid?: true,
+ done?: true,
+ cancelled?: false,
+ client_name: "an_image.jpg",
+ client_relative_path: "",
+ client_size: 2065187,
+ client_type: "image/jpeg",
+ client_last_modified: 1646642130571
+ }
+ assigns = %{entry: entry}
+
+ assert render(~H|<.live_img_preview entry={@entry}/>|) == ~s||
+ end
+
+ test "requires an entry to be given" do
+ assigns = %{}
+
+ assert_raise ArgumentError, "missing required :entry attribute to <.live_img_preview/>", fn ->
+ render(~H|<.live_img_preview />|)
+ end
+ end
+ end
+
+ describe "live_video_preview/1" do
+ test "basic usage" do
+ entry = %Phoenix.LiveView.UploadEntry{
+ progress: 100,
+ preflighted?: true,
+ upload_config: :some_field,
+ upload_ref: "phx-Fz1Xjn4tLhvww0xC",
+ ref: "0",
+ uuid: "e3ae39ee-8251-4e24-9655-d1574adef682",
+ valid?: true,
+ done?: true,
+ cancelled?: false,
+ client_name: "a_video.mp4",
+ client_relative_path: "",
+ client_size: 17116709,
+ client_type: "video/mp4",
+ client_last_modified: 1671742709575
+ }
+ assigns = %{entry: entry}
+
+ assert render(~H|<.live_video_preview entry={@entry}/>|) == ~s||
+ end
+
+ test "requires an entry to be given" do
+ assigns = %{}
+
+ assert_raise ArgumentError, "missing required :entry attribute to <.live_video_preview/>", fn ->
+ render(~H|<.live_video_preview />|)
+ end
+ end
+ end
+
describe "intersperse" do
test "generates form with no options" do
assigns = %{}