fix: refine reference frame previews
This commit is contained in:
@@ -14,6 +14,8 @@ type MediaAssetAction = {
|
||||
tone?: "neutral" | "cyan" | "rose"
|
||||
}
|
||||
|
||||
type MediaAssetPreviewPlacement = "auto" | "left" | "right"
|
||||
|
||||
type MediaAssetTileProps = {
|
||||
kind?: "image" | "video"
|
||||
src?: string
|
||||
@@ -29,6 +31,8 @@ type MediaAssetTileProps = {
|
||||
objectFit?: "contain" | "cover"
|
||||
previewObjectFit?: "contain" | "cover"
|
||||
previewClassName?: string
|
||||
previewPlacement?: MediaAssetPreviewPlacement
|
||||
previewMaxWidth?: number
|
||||
selected?: boolean
|
||||
disabled?: boolean
|
||||
busy?: boolean
|
||||
@@ -55,15 +59,21 @@ function mediaObjectClass(fit: "contain" | "cover") {
|
||||
return fit === "cover" ? "object-cover" : "object-contain"
|
||||
}
|
||||
|
||||
function previewPosition(event: ReactMouseEvent<HTMLElement>) {
|
||||
function previewPosition(event: ReactMouseEvent<HTMLElement>, placement: MediaAssetPreviewPlacement, maxWidth: number) {
|
||||
const margin = 16
|
||||
const previewWidth = Math.min(520, window.innerWidth - margin * 2)
|
||||
const previewWidth = Math.min(maxWidth, window.innerWidth - margin * 2)
|
||||
const previewHeight = Math.min(760, window.innerHeight - margin * 2)
|
||||
let left = event.clientX + 18
|
||||
let left = placement === "left" ? event.clientX - previewWidth - 18 : event.clientX + 18
|
||||
let top = event.clientY + 18
|
||||
if (left + previewWidth > window.innerWidth - margin) left = event.clientX - previewWidth - 18
|
||||
if (placement === "auto" && left + previewWidth > window.innerWidth - margin) left = event.clientX - previewWidth - 18
|
||||
if (placement === "right" && left + previewWidth > window.innerWidth - margin) left = window.innerWidth - previewWidth - margin
|
||||
if (placement === "left" && left < margin) left = margin
|
||||
if (top + previewHeight > window.innerHeight - margin) top = window.innerHeight - previewHeight - margin
|
||||
return { left: Math.max(margin, left), top: Math.max(margin, top) }
|
||||
return {
|
||||
left: Math.max(margin, Math.min(left, window.innerWidth - previewWidth - margin)),
|
||||
top: Math.max(margin, top),
|
||||
width: previewWidth,
|
||||
}
|
||||
}
|
||||
|
||||
export function MediaAssetTile({
|
||||
@@ -81,6 +91,8 @@ export function MediaAssetTile({
|
||||
objectFit = "contain",
|
||||
previewObjectFit,
|
||||
previewClassName = "",
|
||||
previewPlacement = "auto",
|
||||
previewMaxWidth = 520,
|
||||
selected = false,
|
||||
disabled = false,
|
||||
busy = false,
|
||||
@@ -96,7 +108,7 @@ export function MediaAssetTile({
|
||||
actions = [],
|
||||
disablePreview = false,
|
||||
}: MediaAssetTileProps) {
|
||||
const [position, setPosition] = useState<{ left: number; top: number } | null>(null)
|
||||
const [position, setPosition] = useState<{ left: number; top: number; width: number } | null>(null)
|
||||
const mediaSrc = src || poster || ""
|
||||
const canPreview = !!mediaSrc && !disablePreview
|
||||
const fit = mediaObjectClass(objectFit)
|
||||
@@ -104,7 +116,7 @@ export function MediaAssetTile({
|
||||
|
||||
const updatePreview = (event: ReactMouseEvent<HTMLElement>) => {
|
||||
if (!canPreview) return
|
||||
setPosition(previewPosition(event))
|
||||
setPosition(previewPosition(event, previewPlacement, previewMaxWidth))
|
||||
}
|
||||
|
||||
const media = kind === "video" && src ? (
|
||||
@@ -136,7 +148,7 @@ export function MediaAssetTile({
|
||||
? createPortal(
|
||||
<div
|
||||
className={`pointer-events-none fixed z-[10000] w-[min(520px,calc(100vw-32px))] rounded-xl border border-white/15 bg-black/94 p-3 shadow-[0_28px_80px_rgba(0,0,0,0.72)] ${previewClassName}`}
|
||||
style={{ left: position.left, top: position.top }}
|
||||
style={{ left: position.left, top: position.top, width: position.width }}
|
||||
>
|
||||
<div className="flex max-h-[min(76vh,720px)] items-center justify-center overflow-hidden rounded-lg bg-black">
|
||||
{kind === "video" && src ? (
|
||||
|
||||
Reference in New Issue
Block a user