| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- 'use client';
- import { useCallback, useEffect, useState } from 'react';
- import { createPortal } from 'react-dom';
- import { ChevronLeft, ChevronRight, X } from 'lucide-react';
- type Props = {
- urls: string[];
- startIndex: number;
- onClose: () => void;
- };
- export default function FeedLightbox({ urls, startIndex, onClose }: Props) {
- const [index, setIndex] = useState(startIndex);
- const [mounted, setMounted] = useState(false);
- useEffect(() => {
- setMounted(true);
- }, []);
- const next = useCallback(() => {
- setIndex((i) => (i + 1) % urls.length);
- }, [urls.length]);
- const prev = useCallback(() => {
- setIndex((i) => (i - 1 + urls.length) % urls.length);
- }, [urls.length]);
- useEffect(() => {
- const handleKey = (e: KeyboardEvent) => {
- if (e.key === 'Escape') {
- onClose();
- } else if (e.key === 'ArrowRight') {
- next();
- } else if (e.key === 'ArrowLeft') {
- prev();
- }
- };
- document.addEventListener('keydown', handleKey);
- document.body.style.overflow = 'hidden';
- return () => {
- document.removeEventListener('keydown', handleKey);
- document.body.style.overflow = '';
- };
- }, [next, prev, onClose]);
- if (!mounted || urls.length === 0) {
- return null;
- }
- const body = (
- <div className="feed-lightbox" role="dialog" aria-modal="true" onClick={onClose}>
- <button type="button" className="feed-lightbox__close" aria-label="닫기" onClick={onClose}>
- <X size={28} />
- </button>
- {urls.length > 1 && (
- <button type="button" className="feed-lightbox__nav feed-lightbox__nav--prev" aria-label="이전" onClick={(e) => { e.stopPropagation(); prev(); }}>
- <ChevronLeft size={32} />
- </button>
- )}
- <div className="feed-lightbox__stage" onClick={(e) => e.stopPropagation()}>
- <img src={urls[index]} alt={`이미지 ${index + 1}`} className="feed-lightbox__image" />
- {urls.length > 1 && (
- <div className="feed-lightbox__counter">{index + 1} / {urls.length}</div>
- )}
- </div>
- {urls.length > 1 && (
- <button type="button" className="feed-lightbox__nav feed-lightbox__nav--next" aria-label="다음" onClick={(e) => { e.stopPropagation(); next(); }}>
- <ChevronRight size={32} />
- </button>
- )}
- </div>
- );
- return createPortal(body, document.body);
- }
|