MCPcopy
hub / github.com/shiyi-0x7f/o-lib / BookShelf3D

Function BookShelf3D

src/pages/DiscoverPage/BookShelf3D.tsx:22–592  ·  view source on GitHub ↗
({
  books, currentIndex,
  getCoverUrl, handleCoverError,
  onCardClick, onFavorite, onNavigate,
}: BookShelf3DProps)

Source from the content-addressed store, hash-verified

20const VISIBLE_RANGE = 3; // Show ±3 books from center
21
22export default function BookShelf3D({
23 books, currentIndex,
24 getCoverUrl, handleCoverError,
25 onCardClick, onFavorite, onNavigate,
26}: BookShelf3DProps) {
27 const [hoveredCenter, setHoveredCenter] = useState(false);
28 const [favAnimating, setFavAnimating] = useState(false);
29 const wheelCooldown = useRef(false);
30
31 const handleWheel = useCallback((e: React.WheelEvent) => {
32 if (wheelCooldown.current) return;
33 wheelCooldown.current = true;
34 if (e.deltaY > 0 || e.deltaX > 0) {
35 onNavigate('right');
36 } else if (e.deltaY < 0 || e.deltaX < 0) {
37 onNavigate('left');
38 }
39 setTimeout(() => { wheelCooldown.current = false; }, 300);
40 }, [onNavigate]);
41
42 const handleFavoriteClick = (e: React.MouseEvent) => {
43 e.stopPropagation();
44 const book = books[currentIndex];
45 if (!book || favAnimating) return;
46 setFavAnimating(true);
47 onFavorite(book);
48 setTimeout(() => setFavAnimating(false), 600);
49 };
50
51 const centerBook = books[currentIndex];
52 const canGoLeft = currentIndex > 0;
53 const canGoRight = currentIndex < books.length - 1;
54
55 return (
56 <div
57 onWheel={handleWheel}
58 style={{
59 position: 'relative',
60 width: '100%',
61 display: 'flex',
62 flexDirection: 'column',
63 alignItems: 'center',
64 gap: '0px',
65 userSelect: 'none',
66 }}
67 >
68 {/* === Upper section: 3D Bookshelf === */}
69 <div style={{
70 position: 'relative',
71 width: '100%',
72 height: 'calc(100vh - 360px)',
73 minHeight: '320px',
74 maxHeight: '460px',
75 display: 'flex',
76 flexDirection: 'column',
77 alignItems: 'center',
78 justifyContent: 'flex-end',
79 perspective: '1200px',

Callers

nothing calls this directly

Calls 2

formatFileSizeFunction · 0.90
getCoverUrlFunction · 0.85

Tested by

no test coverage detected