feat: initial
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
"use client";
|
||||
|
||||
// Press-to-play / press-to-view preview for uploaded assets.
|
||||
// - audio: a play button that toggles a compact inline <audio> player.
|
||||
// - video: a button that opens the video in a modal player.
|
||||
// - image: a thumbnail that opens the full image in a modal.
|
||||
// Renders a muted dash when no source is available.
|
||||
|
||||
import { useState } from "react";
|
||||
import { Modal } from "./ui";
|
||||
import { PlayIcon, PauseIcon, EyeIcon } from "./icons";
|
||||
|
||||
type Kind = "audio" | "video" | "image";
|
||||
|
||||
export function MediaPreview({
|
||||
src,
|
||||
kind,
|
||||
label,
|
||||
}: {
|
||||
src?: string | null;
|
||||
kind: Kind;
|
||||
label?: string;
|
||||
}) {
|
||||
const [audioOpen, setAudioOpen] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
if (!src) return <span className="text-muted">—</span>;
|
||||
|
||||
if (kind === "audio") {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAudioOpen((v) => !v)}
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-primary-soft text-primary transition hover:bg-primary hover:text-white"
|
||||
aria-label={audioOpen ? "توقف" : "پخش"}
|
||||
>
|
||||
{audioOpen ? (
|
||||
<PauseIcon className="h-4 w-4" />
|
||||
) : (
|
||||
<PlayIcon className="h-4 w-4" />
|
||||
)}
|
||||
</button>
|
||||
{audioOpen && (
|
||||
// eslint-disable-next-line jsx-a11y/media-has-caption
|
||||
<audio
|
||||
src={src}
|
||||
controls
|
||||
autoPlay
|
||||
className="h-8 max-w-[220px]"
|
||||
onEnded={() => setAudioOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (kind === "image") {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setModalOpen(true)}
|
||||
className="block overflow-hidden rounded-lg border border-border transition hover:opacity-80"
|
||||
aria-label="نمایش تصویر"
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={src} alt={label ?? ""} className="h-12 w-12 object-cover" />
|
||||
</button>
|
||||
<Modal
|
||||
open={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
title={label ?? "تصویر"}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={src} alt={label ?? ""} className="mx-auto max-h-[70vh] rounded-lg" />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// video
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setModalOpen(true)}
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-primary-soft text-primary transition hover:bg-primary hover:text-white"
|
||||
aria-label="نمایش ویدیو"
|
||||
>
|
||||
<EyeIcon className="h-4 w-4" />
|
||||
</button>
|
||||
<Modal
|
||||
open={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
title={label ?? "ویدیو"}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
|
||||
<video src={src} controls autoPlay className="w-full rounded-lg" />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user