|
- import { motion } from 'framer-motion'
- import { useRef } from 'react'
- import { useLocation } from 'react-router-dom'
-
- import PrefetchLink from '@/components/PrefetchLink'
- import { useSharedTransitionStore } from '@/stores/sharedTransitionStore'
-
- import type { FC, MouseEvent } from 'react'
-
- import type { Post } from '@/types'
-
- type Props = { posts: Post[]
- onClick?: (event: MouseEvent<HTMLElement>) => void }
-
-
- export default (({ posts, onClick }: Props) => {
- const location = useLocation ()
-
- const setForLocationKey = useSharedTransitionStore (s => s.setForLocationKey)
-
- const cardRef = useRef<HTMLDivElement> (null)
-
- return (
- <div className="flex flex-wrap gap-6 p-4">
- {posts.map ((post, i) => {
- const sharedId = `page-${ post.id }`
- const layoutId = sharedId
-
- return (
- <PrefetchLink
- to={`/posts/${ post.id }`}
- key={post.id}
- className="w-40 h-40"
- state={{ sharedId }}
- onClick={e => {
- setForLocationKey (location.key, sharedId)
- onClick?.(e)
- }}>
- <motion.div
- ref={cardRef}
- layoutId={layoutId}
- className="w-full h-full overflow-hidden rounded-xl shadow
- transform-gpu will-change-transform"
- whileHover={{ scale: 1.02 }}
- onLayoutAnimationStart={() => {
- if (!(cardRef.current))
- return
-
- cardRef.current.style.position = 'relative'
- cardRef.current.style.zIndex = '9999'
- }}
- onLayoutAnimationComplete={() => {
- if (!(cardRef.current))
- return
-
- cardRef.current.style.zIndex = ''
- cardRef.current.style.position = ''
- }}
- transition={{ type: 'spring', stiffness: 500, damping: 40, mass: .5 }}>
- <img src={post.thumbnail || post.thumbnailBase || undefined}
- alt={post.title || post.url}
- title={post.title || post.url || undefined}
- loading={i < 12 ? 'eager' : 'lazy'}
- decoding="async"
- className="object-cover w-full h-full"/>
- </motion.div>
- </PrefetchLink>)
- })}
- </div>)
- }) satisfies FC<Props>
|