@using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @inject IJSRuntime JSRuntime
@if (!string.IsNullOrEmpty(_selectedUrl)) { var type = GetMediaType(_selectedUrl); @if (type == MediaType.Image) {
Main View
} else if (type == MediaType.Video) {
@if (MediaUrls != null && MediaUrls.Count() > 1) {
@foreach (var url in MediaUrls) { var isSelected = url == _selectedUrl; var type = GetMediaType(url); }
}
@code { [Parameter] public IEnumerable MediaUrls { get; set; } = Enumerable.Empty(); [Parameter] public string? Class { get; set; } [Parameter] public int Width { get; set; } = 1; [Parameter] public int Height { get; set; } = 1; [Parameter] public int ThumbSize { get; set; } = 64; private ElementReference _thumbContainer; private string? _selectedUrl; private string _zoomStyle = ""; protected override void OnInitialized() { if (MediaUrls.Any()) _selectedUrl = MediaUrls.First(); } protected override void OnParametersSet() { if (!string.IsNullOrEmpty(_selectedUrl) && !MediaUrls.Contains(_selectedUrl)) { _selectedUrl = MediaUrls.FirstOrDefault(); } else if (string.IsNullOrEmpty(_selectedUrl) && MediaUrls.Any()) { _selectedUrl = MediaUrls.First(); } } private void HandleMouseMove(MouseEventArgs e) { // For a spotlight lens, we need to calculate the percentage of mouse position // We assume a base size or just use a placeholder for now. // Since we can't get the width/height easily, we'll use a standard percentage approach // if we assume the container is roughly the size of viewport or fixed. // Actually, without JS, OffsetX/Y is the only way. // We'll use a rough 600px base for calculation or just standard 0-1 range if we knew bounds. // Let's use a "Magic Lens" approach: double zoomLevel = 2.5; double lensSize = 180; // We'll estimate the percentage by assuming the mouse is within the container bounds. // A better way is to pass the container size via a simplistic JS on resize. // But for now, let's just use the current offset and hope it's reasonably mapped. double posX = e.OffsetX; double posY = e.OffsetY; // We'll just use the raw offsets to position the lens _zoomStyle = $"display: block; left: {posX - (lensSize / 2)}px; top: {posY - (lensSize / 2)}px; " + $"background-image: url('{_selectedUrl}'); " + $"background-size: {zoomLevel * 100}%; " + $"background-position: {(posX / 500.0) * 100}% {(posY / 500.0) * 100}%;"; } private void HandleMouseLeave() { _zoomStyle = "display: none;"; } private async Task SelectMedia(string url) { _selectedUrl = url; HandleMouseLeave(); StateHasChanged(); await ScrollToActiveThumbnail(); } private async Task NextMedia() { var list = MediaUrls.ToList(); var index = list.IndexOf(_selectedUrl ?? ""); if (index != -1) { var nextIndex = (index + 1) % list.Count; await SelectMedia(list[nextIndex]); } } private async Task PreviousMedia() { var list = MediaUrls.ToList(); var index = list.IndexOf(_selectedUrl ?? ""); if (index != -1) { var prevIndex = (index - 1 + list.Count) % list.Count; await SelectMedia(list[prevIndex]); } } private async Task ScrollToActiveThumbnail() { try { await JSRuntime.InvokeVoidAsync("eval", @" var container = document.querySelector('.scrollbar-hide'); if (container) { var activeThumb = container.querySelector('.border-sky-500'); if (activeThumb) { activeThumb.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } } "); } catch { } } private async Task Scroll(int amount) { try { await JSRuntime.InvokeVoidAsync("eval", $"document.querySelector('.scrollbar-hide').scrollBy({{ left: {amount}, behavior: 'smooth' }})"); } catch { } // Fail gracefully if JS is busy } private enum MediaType { Image, Video, YouTube, Vimeo, Unknown } private MediaType GetMediaType(string url) { if (string.IsNullOrWhiteSpace(url)) return MediaType.Image; url = url.ToLower(); if (url.Contains("youtube.com") || url.Contains("youtu.be")) return MediaType.YouTube; if (url.Contains("vimeo.com")) return MediaType.Vimeo; if (url.EndsWith(".mp4") || url.EndsWith(".webm") || url.EndsWith(".ogg")) return MediaType.Video; return MediaType.Image; } private string GetYouTubeId(string url) { if (url.Contains("youtu.be/")) return url.Split("youtu.be/")[1].Split("?")[0]; if (url.Contains("v=")) return url.Split("v=")[1].Split("&")[0]; return ""; } }