feat: news crop editor — natural drag, zoom slider, force-dynamic page

- Rewrite crop preview: drag moves image naturally (inverted focal)
- Add zoom slider (1x-3x) + mouse wheel zoom
- Apply imageZoom on user side (featured, compact, modal)
- Force-dynamic on main page to prevent stale cache
This commit is contained in:
2026-03-26 11:11:39 +03:00
parent 4b6443c867
commit 4c8c6eb0d2
7 changed files with 77 additions and 20 deletions
+8 -2
View File
@@ -52,7 +52,10 @@ function FeaturedArticle({
loading="lazy"
sizes="(min-width: 768px) 80vw, 100vw"
className="object-cover transition-transform duration-700 group-hover:scale-105"
style={{ objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%` }}
style={{
objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%`,
transform: `scale(${item.imageZoom ?? 1})`,
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent" />
</div>
@@ -96,7 +99,10 @@ function CompactArticle({
loading="lazy"
sizes="112px"
className="object-cover transition-transform duration-500 group-hover:scale-105"
style={{ objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%` }}
style={{
objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%`,
transform: `scale(${item.imageZoom ?? 1})`,
}}
/>
</div>
)}
+4 -1
View File
@@ -82,7 +82,10 @@ export function NewsModal({ item, onClose }: NewsModalProps) {
fill
sizes="(min-width: 768px) 672px, 100vw"
className="object-cover"
style={{ objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%` }}
style={{
objectPosition: `${item.imageFocalX ?? 50}% ${item.imageFocalY ?? 50}%`,
transform: `scale(${item.imageZoom ?? 1})`,
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-[#0a0a0a] via-transparent to-transparent" />
</div>