mirror of
https://github.com/chenasraf/stimvisor.git
synced 2026-05-18 01:39:07 +00:00
feat: keyboard navigation in carousel
This commit is contained in:
@@ -1 +1 @@
|
||||
0245f6e720b08c65d698b6a896bdaf7a
|
||||
96a8176a62058aaf100c8e8139826079
|
||||
@@ -2,14 +2,6 @@ import { HtmlProps } from '@/common/types'
|
||||
import { cn } from '@/common/utils'
|
||||
import { screenshots } from '$models'
|
||||
import { DialogContent, DialogTitle } from '@/components/ui/dialog'
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselNext,
|
||||
CarouselPrevious,
|
||||
useCarousel,
|
||||
} from '../ui/carousel'
|
||||
import { ScreenshotImg } from '../ScreenshotImg/ScreenshotImg'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { Button } from '../ui/button'
|
||||
@@ -40,17 +32,36 @@ export function ScreenshotsCarouselModal(
|
||||
|
||||
return vis
|
||||
}, [idx, screenshots])
|
||||
|
||||
const prevScreenshot = useCallback(
|
||||
() => setIdx((i) => (i === 0 ? screenshots.length - 1 : --i)),
|
||||
[screenshots.length],
|
||||
)
|
||||
const nextScreenshot = useCallback(
|
||||
() => setIdx((i) => (i === screenshots.length ? 0 : ++i)),
|
||||
[screenshots.length],
|
||||
)
|
||||
|
||||
const handleKeyUp = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
e.preventDefault()
|
||||
if (e.key === 'ArrowRight') {
|
||||
e.preventDefault()
|
||||
nextScreenshot()
|
||||
} else if (e.key === 'ArrowLeft') {
|
||||
e.preventDefault()
|
||||
prevScreenshot()
|
||||
}
|
||||
},
|
||||
[nextScreenshot, prevScreenshot],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={cn('', className)} {...rest}>
|
||||
<div className={cn('', className)} {...rest} onKeyUp={handleKeyUp}>
|
||||
<DialogContent className="max-w-[calc(100%_-_128px)] max-h-[calc(100%_-_64px)]">
|
||||
<DialogTitle>Screenshots</DialogTitle>
|
||||
<div className="flex gap-4 items-center w-full">
|
||||
<Button
|
||||
className="flex-shrink-0"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => setIdx((i) => (i === 0 ? screenshots.length - 1 : --i))}
|
||||
>
|
||||
<Button className="flex-shrink-0" variant="outline" size="icon" onClick={prevScreenshot}>
|
||||
<FaAngleLeft />
|
||||
</Button>
|
||||
<div className="flex-grow flex place-content-center">
|
||||
@@ -62,12 +73,7 @@ export function ScreenshotsCarouselModal(
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
className="flex-shrink-0"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => setIdx((i) => (i === screenshots.length ? 0 : ++i))}
|
||||
>
|
||||
<Button className="flex-shrink-0" variant="outline" size="icon" onClick={nextScreenshot}>
|
||||
<FaAngleRight />
|
||||
</Button>
|
||||
</div>
|
||||
@@ -75,50 +81,3 @@ export function ScreenshotsCarouselModal(
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// <Carousel opts={{ startIndex: activeIndex ?? undefined, loop: false }}>
|
||||
// <CarouselInner {...props} />
|
||||
// <CarouselPrevious />
|
||||
// <CarouselNext />
|
||||
// </Carousel>
|
||||
|
||||
// function CarouselInner({
|
||||
// activeIndex,
|
||||
// screenshots,
|
||||
// }: React.ComponentProps<typeof ScreenshotsCarouselModal>) {
|
||||
// const carousel = useCarousel()
|
||||
// const [inView, setInView] = useState(() => carousel.api?.slidesInView() ?? [])
|
||||
// const isInView = useCallback(
|
||||
// (idx: number) =>
|
||||
// [-2, -1, 0, 1, 2].map((x) => idx + x).some((x) => activeIndex === x || inView.includes(x)),
|
||||
// [activeIndex, inView],
|
||||
// )
|
||||
//
|
||||
// useEffect(() => {
|
||||
// if (!carousel.api) {
|
||||
// return
|
||||
// }
|
||||
// const { api } = carousel
|
||||
// const cb = () => {
|
||||
// setInView(api.slidesInView() ?? [])
|
||||
// }
|
||||
// api.on('slidesInView', cb)
|
||||
// return () => {
|
||||
// api.off('slidesInView', cb)
|
||||
// }
|
||||
// }, [carousel])
|
||||
//
|
||||
// return (
|
||||
// <CarouselContent className="max-h-full">
|
||||
// {screenshots.map((scr, i) => (
|
||||
// <CarouselItem key={scr.path} className="flex items-center justify-center">
|
||||
// <ScreenshotImg
|
||||
// screenshot={scr}
|
||||
// load={isInView(i)}
|
||||
// className="max-h-[calc(100vh_-_160px)] object-cover"
|
||||
// />
|
||||
// </CarouselItem>
|
||||
// ))}
|
||||
// </CarouselContent>
|
||||
// )
|
||||
// }
|
||||
|
||||
@@ -4,7 +4,7 @@ import { LoadingContainer } from '@/components/Loader/LoadingContainer'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { FaAngleLeft } from 'react-icons/fa6'
|
||||
import { ScreenshotImg } from '@/components/ScreenshotImg/ScreenshotImg'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { ScreenshotsCarouselModal } from '@/components/ScreenshotsCarouselModal/ScreenshotsCarouselModal'
|
||||
import { Dialog } from '@/components/ui/dialog'
|
||||
import { useGameScreenshots } from '@/common/hooks/useScreenshots'
|
||||
@@ -28,6 +28,7 @@ function ScreenshotsGamePage() {
|
||||
setModalIndex(null)
|
||||
}, [])
|
||||
|
||||
const [headerRef, setHeaderRef] = useStateRef<HTMLDivElement | null>(null)
|
||||
const [gridRef, setGridRef] = useStateRef<HTMLDivElement | null>(null)
|
||||
const getColCount = useCallback(
|
||||
() => Math.floor((gridRef?.clientWidth ?? window.innerWidth) / thumbSize),
|
||||
@@ -77,7 +78,7 @@ function ScreenshotsGamePage() {
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="sticky top-0 p-4 bg-background flex flex-col gap-2 z-10">
|
||||
<div className="sticky top-0 p-4 bg-background flex flex-col gap-2 z-10" ref={setHeaderRef}>
|
||||
<div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link to="/screenshots">
|
||||
@@ -109,7 +110,7 @@ function ScreenshotsGamePage() {
|
||||
<FixedSizeGrid
|
||||
columnCount={colCount}
|
||||
columnWidth={thumbSize}
|
||||
height={window.innerHeight - 200}
|
||||
height={window.innerHeight - (headerRef?.clientHeight ?? 200)}
|
||||
rowCount={Math.ceil((dir.screenshots?.length ?? 0) / colCount)}
|
||||
rowHeight={168}
|
||||
width={colCount * (thumbSize + 4)}
|
||||
|
||||
Reference in New Issue
Block a user