use maud::{html, Markup}; use crate::page::icon; pub struct Item { /// The image's address. Empty for a video, which has no image. pub src: String, pub cid: String, pub mime_type: String, pub size: u64, /// A YouTube video's link, in place of an image's `cid`, `mime_type`, /// and `size`. pub url: String, pub alt: String, } /// A reorderable drag-and-drop list of media items that also owns its file /// input, YouTube link input, progress bar, and hidden form field. Each image /// uploads immediately on selection; the finished order serialises into /// `name` on submit. pub fn render(endpoint: &str, name: &str, items: &[Item]) -> Markup { html! { media-input endpoint=(endpoint) { @for item in items { div.item data-cid=(item.cid) data-mime-type=(item.mime_type) data-size=(item.size) data-url=(item.url) { span.handle draggable="true" aria-hidden="true" { (icon(icondata::LuGripVertical)) } @if item.src.is_empty() { span.video-preview aria-hidden="true" { (icon(icondata::LuYoutube)) } } @else { img src=(item.src) alt=""; } @let what = if item.url.is_empty() { "image" } else { "video" }; input type="text" class="alt" placeholder={ "Describe this " (what) } aria-label={ "Describe this " (what) } value=[(!item.alt.is_empty()).then_some(&item.alt)]; button type="button" class="remove" aria-label={ "Remove " (what) } { (icon(icondata::LuX)) } } } label.button.secondary { (icon(icondata::LuUpload)) "Add images" input.visually-hidden type="file" accept="image/*" multiple; } div.youtube-add { input type="url" class="youtube-url" placeholder="Paste a YouTube link" aria-label="YouTube link"; button type="button" class="secondary" { (icon(icondata::LuYoutube)) "Add video" } } progress max="100" value="0" hidden {} input type="hidden" name=(name); } } }