react-3d-flipbook 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,1005 @@
1
+ # React 3D Flipbook
2
+
3
+ A modern, feature-rich React library for creating beautiful, interactive 3D flipbooks with realistic page-turning effects powered by WebGL and Three.js.
4
+
5
+ ---
6
+
7
+ ## Features
8
+
9
+ - 🎮 **WebGL 3D Rendering**: Realistic page-flip animations with Three.js
10
+ - 📄 **PDF Support**: Direct PDF rendering with automatic page sizing via PDF.js
11
+ - 📐 **Dynamic Page Sizing**: Automatically adapts to PDF page dimensions
12
+ - 💡 **Dynamic Lighting**: Configurable lights and shadows for depth
13
+ - 📱 **Responsive Design**: Works seamlessly on desktop, tablet, and mobile devices
14
+ - 🔍 **Zoom Controls**: Pinch-to-zoom, mouse wheel, and button controls
15
+ - 🔖 **Bookmarks**: Save, manage, and persist bookmarked pages
16
+ - 📑 **Table of Contents**: Hierarchical, searchable TOC navigation
17
+ - 🖼️ **Thumbnails Panel**: Visual page thumbnail navigation
18
+ - 🔎 **Full-Text Search**: Search across all pages with highlighted results
19
+ - ▶️ **Autoplay**: Automatic page flipping with customizable intervals
20
+ - 🌙 **Themes**: Light, dark, and gradient themes with full customization
21
+ - ♿ **Accessible**: ARIA labels, screen reader support, and keyboard navigation
22
+ - 📦 **TypeScript**: Complete TypeScript definitions for type safety
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ```sh
29
+ npm install react-3d-flipbook
30
+ # or
31
+ yarn add react-3d-flipbook
32
+ ```
33
+
34
+ ### Required Peer Dependencies
35
+
36
+ ```sh
37
+ npm install three @types/three
38
+ ```
39
+
40
+ ### Optional (for PDF support)
41
+
42
+ ```sh
43
+ npm install pdfjs-dist
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Quick Start
49
+
50
+ ### Basic Usage with Images
51
+
52
+ ```tsx
53
+ import { Flipbook } from 'react-3d-flipbook';
54
+ import 'react-3d-flipbook/dist/styles.css';
55
+
56
+ const pages = [
57
+ { src: '/images/page1.jpg', title: 'Cover' },
58
+ { src: '/images/page2.jpg', title: 'Introduction' },
59
+ // ...more pages
60
+ ];
61
+
62
+ function App() {
63
+ return (
64
+ <Flipbook
65
+ pages={pages}
66
+ width={800}
67
+ height={600}
68
+ onPageFlip={e => console.log('Flipped to page', e.page)}
69
+ />
70
+ );
71
+ }
72
+ ```
73
+
74
+ ### PDF Support
75
+
76
+ ```tsx
77
+ import { useState, useEffect } from 'react';
78
+ import { Flipbook, pdfToFlipbookPages, setPdfWorkerSrc } from 'react-3d-flipbook';
79
+ import 'react-3d-flipbook/dist/styles.css';
80
+
81
+ // Set up PDF.js worker (required once)
82
+ setPdfWorkerSrc('https://unpkg.com/pdfjs-dist@4.0.379/build/pdf.worker.mjs');
83
+
84
+ function PdfFlipbook() {
85
+ const [pages, setPages] = useState([]);
86
+ const [loading, setLoading] = useState(true);
87
+
88
+ useEffect(() => {
89
+ async function loadPdf() {
90
+ const loadedPages = await pdfToFlipbookPages('/path/to/document.pdf', {
91
+ scale: 1.5,
92
+ format: 'jpeg',
93
+ quality: 0.8,
94
+ onProgress: (current, total) => console.log(`Loading ${current}/${total}`)
95
+ });
96
+ setPages(loadedPages);
97
+ setLoading(false);
98
+ }
99
+ loadPdf();
100
+ }, []);
101
+
102
+ if (loading) return <div>Loading PDF...</div>;
103
+
104
+ return (
105
+ <Flipbook
106
+ pages={pages}
107
+ width={800}
108
+ height={600}
109
+ singlePageMode={false}
110
+ />
111
+ );
112
+ }
113
+ ```
114
+
115
+ ### PDF with Auto-Sizing
116
+
117
+ The flipbook automatically sizes pages based on the PDF's actual dimensions:
118
+
119
+ ```tsx
120
+ import {
121
+ Flipbook,
122
+ pdfToFlipbookPages,
123
+ calculateFlipbookSizeFromPages,
124
+ setPdfWorkerSrc
125
+ } from 'react-3d-flipbook';
126
+
127
+ setPdfWorkerSrc('https://unpkg.com/pdfjs-dist@4.0.379/build/pdf.worker.mjs');
128
+
129
+ function AutoSizedPdfFlipbook() {
130
+ const [pages, setPages] = useState([]);
131
+ const [size, setSize] = useState({ width: 800, height: 600 });
132
+
133
+ useEffect(() => {
134
+ async function loadPdf() {
135
+ const loadedPages = await pdfToFlipbookPages('/document.pdf');
136
+ setPages(loadedPages);
137
+
138
+ // Calculate optimal container size based on PDF page dimensions
139
+ const calculatedSize = calculateFlipbookSizeFromPages(loadedPages, {
140
+ singlePageMode: false,
141
+ maxWidth: 1200,
142
+ maxHeight: 800,
143
+ });
144
+
145
+ if (calculatedSize) {
146
+ setSize(calculatedSize);
147
+ }
148
+ }
149
+ loadPdf();
150
+ }, []);
151
+
152
+ return (
153
+ <Flipbook
154
+ pages={pages}
155
+ width={size.width}
156
+ height={size.height}
157
+ />
158
+ );
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## PDF Utilities
165
+
166
+ ### `setPdfWorkerSrc(workerSrc: string)`
167
+
168
+ Set the PDF.js worker source URL. Must be called before using any PDF functions.
169
+
170
+ ```tsx
171
+ import { setPdfWorkerSrc } from 'react-3d-flipbook';
172
+
173
+ // Using CDN
174
+ setPdfWorkerSrc('https://unpkg.com/pdfjs-dist@4.0.379/build/pdf.worker.mjs');
175
+
176
+ // Using local file (Vite)
177
+ import workerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
178
+ setPdfWorkerSrc(workerSrc);
179
+ ```
180
+
181
+ ### `pdfToFlipbookPages(source, options)`
182
+
183
+ Convert a PDF to flipbook pages.
184
+
185
+ ```tsx
186
+ import { pdfToFlipbookPages } from 'react-3d-flipbook';
187
+
188
+ const pages = await pdfToFlipbookPages('/document.pdf', {
189
+ scale: 2, // Render scale (default: 2)
190
+ format: 'jpeg', // 'png' or 'jpeg' (default: 'png')
191
+ quality: 0.92, // JPEG quality 0-1 (default: 0.92)
192
+ pageNumbers: [1, 2, 5], // Specific pages to render (optional)
193
+ onProgress: (current, total) => console.log(`${current}/${total}`)
194
+ });
195
+ ```
196
+
197
+ **Returns:** `Promise<FlipbookPage[]>` - Array of pages with `src`, `width`, `height`, and `orientation`.
198
+
199
+ ### `pdfToFlipbookPagesLazy(source, options)`
200
+
201
+ Lazy/streaming PDF page loading for memory efficiency.
202
+
203
+ ```tsx
204
+ import { pdfToFlipbookPagesLazy } from 'react-3d-flipbook';
205
+
206
+ const pages = [];
207
+ for await (const page of pdfToFlipbookPagesLazy('/large-document.pdf')) {
208
+ pages.push(page);
209
+ // Update UI progressively
210
+ setPages([...pages]);
211
+ }
212
+ ```
213
+
214
+ ### `getPdfInfo(source)`
215
+
216
+ Get PDF document info without rendering pages.
217
+
218
+ ```tsx
219
+ import { getPdfInfo } from 'react-3d-flipbook';
220
+
221
+ const info = await getPdfInfo('/document.pdf');
222
+ console.log(info.numPages); // Total pages
223
+ console.log(info.pageInfos); // Array of { pageNumber, width, height, orientation }
224
+ ```
225
+
226
+ ### `calculateFlipbookSize(pageWidth, pageHeight, options)`
227
+
228
+ Calculate optimal flipbook container size based on page dimensions.
229
+
230
+ ```tsx
231
+ import { calculateFlipbookSize } from 'react-3d-flipbook';
232
+
233
+ const size = calculateFlipbookSize(595, 842, { // A4 dimensions
234
+ singlePageMode: false,
235
+ maxWidth: 1200,
236
+ maxHeight: 800,
237
+ });
238
+
239
+ console.log(size.width); // Calculated container width
240
+ console.log(size.height); // Calculated container height
241
+ console.log(size.aspectRatio); // Container aspect ratio
242
+ console.log(size.isLandscape); // Whether page is landscape
243
+ ```
244
+
245
+ ### `calculateFlipbookSizeFromPages(pages, options)`
246
+
247
+ Calculate optimal size from a FlipbookPage array using the first page's dimensions.
248
+
249
+ ```tsx
250
+ import { calculateFlipbookSizeFromPages } from 'react-3d-flipbook';
251
+
252
+ const pages = await pdfToFlipbookPages('/document.pdf');
253
+ const size = calculateFlipbookSizeFromPages(pages, {
254
+ singlePageMode: true,
255
+ maxWidth: 1000,
256
+ maxHeight: 700,
257
+ });
258
+
259
+ if (size) {
260
+ console.log(`Container: ${size.width}x${size.height}`);
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## API Reference
267
+
268
+ ### `<Flipbook />` Props
269
+
270
+ | Prop | Type | Default | Description |
271
+ |------------------------|--------------------------------------|------------------------|----------------------------------------------|
272
+ | `pages` | `FlipbookPage[]` | **Required** | Array of page objects |
273
+ | `width` | `string \| number` | `'100%'` | Container width |
274
+ | `height` | `string \| number` | `'600px'` | Container height |
275
+ | `skin` | `'dark' \| 'light' \| 'gradient'` | `'dark'` | Theme/skin |
276
+ | `backgroundColor` | `string` | `'rgb(81,85,88)'` | Background color |
277
+ | `startPage` | `number` | `1` | Initial page |
278
+ | `rightToLeft` | `boolean` | `false` | RTL reading direction |
279
+ | `singlePageMode` | `boolean` | `false` | Show one page at a time |
280
+ | `sideNavigationButtons`| `boolean` | `true` | Show side nav buttons |
281
+ | `hideMenu` | `boolean` | `false` | Hide the toolbar |
282
+ | `zoomMin` | `number` | `1` | Minimum zoom level |
283
+ | `zoomMax2` | `number` | `3` | Maximum zoom level |
284
+ | `zoomStep` | `number` | `0.5` | Zoom increment |
285
+ | `touchSwipeEnabled` | `boolean` | `true` | Enable touch swipe |
286
+ | `tableOfContent` | `TocItem[]` | `undefined` | Table of contents data |
287
+
288
+ #### WebGL 3D Props
289
+
290
+ | Prop | Type | Default | Description |
291
+ |-------------------|-----------|---------|-----------------------------------|
292
+ | `pageFlipDuration`| `number` | `600` | Flip animation duration (ms) |
293
+ | `pageHardness` | `number` | `0.5` | Page flexibility (0-1) |
294
+ | `coverHardness` | `number` | `0.9` | Cover rigidity (0-1) |
295
+ | `shadows` | `boolean` | `true` | Enable shadows |
296
+ | `shadowOpacity` | `number` | `0.3` | Shadow intensity (0-1) |
297
+ | `lights` | `boolean` | `true` | Enable dynamic lighting |
298
+ | `lightIntensity` | `number` | `1` | Light brightness |
299
+ | `pageRoughness` | `number` | `0.8` | Material roughness (0-1) |
300
+ | `pageMetalness` | `number` | `0.1` | Material metalness (0-1) |
301
+ | `antialias` | `boolean` | `true` | Enable antialiasing |
302
+
303
+ #### Camera & Display Props
304
+
305
+ | Prop | Type | Default | Description |
306
+ |-------------------|-----------|---------|----------------------------------------------------------|
307
+ | `cameraZoom` | `number` | `1.35` | Camera zoom/margin factor - higher moves camera back |
308
+ | `pageScale` | `number` | `6` | Base page scale in world units - affects page size |
309
+ | `cameraPositionY` | `number` | `0` | Camera vertical position offset |
310
+ | `cameraLookAtY` | `number` | `0` | Camera look-at Y position |
311
+ | `cameraFov` | `number` | `45` | Field of view in degrees |
312
+
313
+ **Usage Example:**
314
+
315
+ ```tsx
316
+ // Zoom out to show more padding around the book
317
+ <Flipbook
318
+ pages={pages}
319
+ width={800}
320
+ height={600}
321
+ cameraZoom={1.5} // Further back (default: 1.35)
322
+ />
323
+
324
+ // Zoom in to fill more of the container
325
+ <Flipbook
326
+ pages={pages}
327
+ width={800}
328
+ height={600}
329
+ cameraZoom={1.1} // Closer (less padding)
330
+ />
331
+
332
+ // Adjust camera angle for a different perspective
333
+ <Flipbook
334
+ pages={pages}
335
+ width={800}
336
+ height={600}
337
+ cameraPositionY={-1} // Camera slightly below center
338
+ cameraLookAtY={0.5} // Looking slightly upward
339
+ />
340
+
341
+ // Make pages larger in the scene
342
+ <Flipbook
343
+ pages={pages}
344
+ width={800}
345
+ height={600}
346
+ pageScale={8} // Larger pages (default: 6)
347
+ />
348
+ ```
349
+
350
+ #### Event Callbacks
351
+
352
+ | Prop | Type | Description |
353
+ |------------------------|-----------------------------------------|---------------------------------------------|
354
+ | `onPageFlip` | `(e: { page, direction }) => void` | Called when page changes |
355
+ | `onPageFlipStart` | `(e: { page, direction }) => void` | Called when flip starts |
356
+ | `onPageFlipEnd` | `(e: { page }) => void` | Called when flip ends |
357
+ | `onZoomChange` | `(e: { zoom }) => void` | Called when zoom changes |
358
+ | `onReady` | `() => void` | Called when flipbook is ready |
359
+ | `onFullscreenChange` | `(e: { isFullscreen }) => void` | Called on fullscreen toggle |
360
+ | `onLoadProgress` | `(e: { progress }) => void` | Called during loading |
361
+
362
+ ### `FlipbookPage` Type
363
+
364
+ ```ts
365
+ interface FlipbookPage {
366
+ src: string; // Image source URL (required)
367
+ thumb?: string; // Thumbnail image URL
368
+ title?: string; // Page title for TOC
369
+ htmlContent?: string; // HTML content overlay
370
+ empty?: boolean; // Whether this is a blank page
371
+ width?: number; // Page width in pixels (for PDF pages)
372
+ height?: number; // Page height in pixels (for PDF pages)
373
+ orientation?: 'portrait' | 'landscape'; // Page orientation
374
+ }
375
+ ```
376
+
377
+ ---
378
+
379
+ ## Display Modes
380
+
381
+ ### Two-Page Spread Mode (Default)
382
+
383
+ Displays two pages side by side like an open book. Pages flip from right to left with a realistic 3D curl animation.
384
+
385
+ ```tsx
386
+ <Flipbook
387
+ pages={pages}
388
+ width={1200}
389
+ height={800}
390
+ singlePageMode={false}
391
+ />
392
+ ```
393
+
394
+ ### Single-Page Mode
395
+
396
+ Displays one page at a time with a fly-out animation when navigating.
397
+
398
+ ```tsx
399
+ <Flipbook
400
+ pages={pages}
401
+ width={600}
402
+ height={800}
403
+ singlePageMode={true}
404
+ />
405
+ ```
406
+
407
+ ---
408
+
409
+ ## Dynamic Page Sizing
410
+
411
+ The flipbook automatically handles PDFs with varying page sizes:
412
+
413
+ - **Consistent sizing**: All pages are scaled to match the first page's aspect ratio for a uniform appearance
414
+ - **Automatic camera adjustment**: The camera distance adjusts to frame the content properly
415
+ - **Portrait & Landscape support**: Works with both portrait and landscape PDFs
416
+
417
+ ### How It Works
418
+
419
+ 1. When loading a PDF, each page's `width` and `height` are stored in the `FlipbookPage` object
420
+ 2. The flipbook uses the first page's dimensions as the reference for all pages
421
+ 3. The camera automatically calculates the optimal distance to display the content with appropriate margins
422
+ 4. In two-page mode, the spread width is doubled for proper framing
423
+
424
+ ---
425
+
426
+ ## Panels
427
+
428
+ ### Thumbnails Panel
429
+
430
+ ```tsx
431
+ import { ThumbnailsPanel } from 'react-3d-flipbook';
432
+
433
+ <ThumbnailsPanel
434
+ pages={pages}
435
+ currentPage={currentPage}
436
+ isOpen={showThumbnails}
437
+ position="left"
438
+ thumbnailSize={120}
439
+ showPageNumbers={true}
440
+ onPageSelect={goToPage}
441
+ onClose={() => setShowThumbnails(false)}
442
+ />
443
+ ```
444
+
445
+ ### Table of Contents
446
+
447
+ ```tsx
448
+ import { TableOfContents, TocItem } from 'react-3d-flipbook';
449
+
450
+ const tocItems: TocItem[] = [
451
+ {
452
+ title: 'Chapter 1',
453
+ page: 1,
454
+ children: [
455
+ { title: 'Section 1.1', page: 2 },
456
+ { title: 'Section 1.2', page: 5 },
457
+ ],
458
+ },
459
+ { title: 'Chapter 2', page: 10 },
460
+ ];
461
+
462
+ <TableOfContents
463
+ items={tocItems}
464
+ currentPage={currentPage}
465
+ isOpen={showToc}
466
+ position="left"
467
+ closeOnClick={true}
468
+ onPageSelect={goToPage}
469
+ onClose={() => setShowToc(false)}
470
+ />
471
+ ```
472
+
473
+ ### Search Panel
474
+
475
+ ```tsx
476
+ import { SearchPanel } from 'react-3d-flipbook';
477
+
478
+ <SearchPanel
479
+ pages={pages}
480
+ pageTextContent={textContentMap}
481
+ currentPage={currentPage}
482
+ isOpen={showSearch}
483
+ position="left"
484
+ minQueryLength={2}
485
+ maxResults={100}
486
+ highlightColor="#ffeb3b"
487
+ onPageSelect={goToPage}
488
+ onClose={() => setShowSearch(false)}
489
+ />
490
+ ```
491
+
492
+ ### Bookmarks Panel
493
+
494
+ ```tsx
495
+ import { BookmarksPanel } from 'react-3d-flipbook';
496
+
497
+ <BookmarksPanel
498
+ pages={pages}
499
+ bookmarks={bookmarkedPages}
500
+ currentPage={currentPage}
501
+ isOpen={showBookmarks}
502
+ position="left"
503
+ showThumbnails={true}
504
+ onPageSelect={goToPage}
505
+ onRemoveBookmark={removeBookmark}
506
+ onClose={() => setShowBookmarks(false)}
507
+ />
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Hooks
513
+
514
+ ### useFlipbook
515
+
516
+ ```tsx
517
+ import { useFlipbook } from 'react-3d-flipbook';
518
+
519
+ function CustomFlipbook({ pages }) {
520
+ const {
521
+ currentPage,
522
+ numPages,
523
+ zoom,
524
+ isFullscreen,
525
+ isLoading,
526
+ canGoNext,
527
+ canGoPrev,
528
+ bookmarkedPages,
529
+ containerRef,
530
+ nextPage,
531
+ prevPage,
532
+ firstPage,
533
+ lastPage,
534
+ goToPage,
535
+ zoomIn,
536
+ zoomOut,
537
+ zoomTo,
538
+ toggleFullscreen,
539
+ toggleBookmark,
540
+ isPageBookmarked,
541
+ } = useFlipbook({
542
+ pages,
543
+ initialPage: 1,
544
+ zoomMin: 1,
545
+ zoomMax2: 3,
546
+ onPageChange: (page) => console.log('Page:', page),
547
+ });
548
+
549
+ return (
550
+ <div ref={containerRef}>
551
+ {/* Your custom UI */}
552
+ </div>
553
+ );
554
+ }
555
+ ```
556
+
557
+ ### useAutoplay
558
+
559
+ ```tsx
560
+ import { useAutoplay } from 'react-3d-flipbook';
561
+
562
+ function AutoplayFlipbook({ pages }) {
563
+ const [currentPage, setCurrentPage] = useState(1);
564
+
565
+ const {
566
+ isPlaying,
567
+ isPaused,
568
+ interval,
569
+ progress,
570
+ start,
571
+ stop,
572
+ pause,
573
+ resume,
574
+ toggle,
575
+ setInterval,
576
+ skipNext,
577
+ reset,
578
+ } = useAutoplay({
579
+ numPages: pages.length,
580
+ currentPage,
581
+ interval: 3000,
582
+ loop: true,
583
+ autoStart: false,
584
+ pageIncrement: 2,
585
+ onPageChange: (page) => setCurrentPage(page),
586
+ onComplete: () => console.log('Autoplay completed'),
587
+ });
588
+
589
+ return (
590
+ <div>
591
+ <button onClick={toggle}>
592
+ {isPlaying ? (isPaused ? 'Resume' : 'Pause') : 'Play'}
593
+ </button>
594
+ <progress value={progress} max={1} />
595
+ </div>
596
+ );
597
+ }
598
+ ```
599
+
600
+ ### usePdfLoader
601
+
602
+ ```tsx
603
+ import { usePdfLoader } from 'react-3d-flipbook';
604
+
605
+ function PdfViewer() {
606
+ const {
607
+ isAvailable,
608
+ isLoading,
609
+ progress,
610
+ error,
611
+ numPages,
612
+ pages,
613
+ textContent,
614
+ loadPdf,
615
+ renderPage,
616
+ getPageText,
617
+ destroy,
618
+ } = usePdfLoader({
619
+ source: '/path/to/document.pdf',
620
+ workerSrc: '/pdf.worker.min.js',
621
+ scale: 1.5,
622
+ extractText: true,
623
+ onLoadProgress: (p) => console.log(`Loading: ${p * 100}%`),
624
+ onLoadComplete: (n) => console.log(`Loaded ${n} pages`),
625
+ });
626
+
627
+ if (isLoading) {
628
+ return <div>Loading... {Math.round(progress * 100)}%</div>;
629
+ }
630
+
631
+ return <Flipbook pages={pages} />;
632
+ }
633
+ ```
634
+
635
+ ### useSwipeGesture
636
+
637
+ ```tsx
638
+ import { useSwipeGesture } from 'react-3d-flipbook';
639
+
640
+ function SwipeableComponent() {
641
+ const ref = useRef<HTMLDivElement>(null);
642
+
643
+ useSwipeGesture(
644
+ ref,
645
+ () => console.log('Swiped left'),
646
+ () => console.log('Swiped right'),
647
+ { threshold: 50, enabled: true }
648
+ );
649
+
650
+ return <div ref={ref}>Swipe me!</div>;
651
+ }
652
+ ```
653
+
654
+ ### useWheelZoom
655
+
656
+ ```tsx
657
+ import { useWheelZoom } from 'react-3d-flipbook';
658
+
659
+ function ZoomableComponent() {
660
+ const ref = useRef<HTMLDivElement>(null);
661
+ const [zoom, setZoom] = useState(1);
662
+
663
+ useWheelZoom(
664
+ ref,
665
+ (delta) => setZoom((z) => Math.max(0.5, Math.min(3, z + delta))),
666
+ { enabled: true, sensitivity: 0.001 }
667
+ );
668
+
669
+ return <div ref={ref} style={{ transform: `scale(${zoom})` }}>Zoom me!</div>;
670
+ }
671
+ ```
672
+
673
+ ---
674
+
675
+ ## Instance Methods
676
+
677
+ Access via `ref`:
678
+
679
+ ```tsx
680
+ const flipbookRef = useRef<FlipbookInstance>(null);
681
+
682
+ // Navigation
683
+ flipbookRef.current?.nextPage();
684
+ flipbookRef.current?.prevPage();
685
+ flipbookRef.current?.firstPage();
686
+ flipbookRef.current?.lastPage();
687
+ flipbookRef.current?.goToPage(5);
688
+
689
+ // Zoom
690
+ flipbookRef.current?.zoomIn();
691
+ flipbookRef.current?.zoomOut();
692
+ flipbookRef.current?.zoomTo(1.5);
693
+
694
+ // State
695
+ flipbookRef.current?.getCurrentPage();
696
+ flipbookRef.current?.getNumPages();
697
+ flipbookRef.current?.getZoom();
698
+ flipbookRef.current?.isFullscreen();
699
+
700
+ // Fullscreen
701
+ flipbookRef.current?.toggleFullscreen();
702
+
703
+ // Bookmarks
704
+ flipbookRef.current?.bookmarkPage(5);
705
+ flipbookRef.current?.removeBookmark(5);
706
+ flipbookRef.current?.getBookmarkedPages();
707
+
708
+ // Cleanup
709
+ flipbookRef.current?.destroy();
710
+ ```
711
+
712
+ ---
713
+
714
+ ## Styling & Theming
715
+
716
+ ### Built-in Themes
717
+
718
+ ```tsx
719
+ <Flipbook pages={pages} skin="dark" /> // Default dark theme
720
+ <Flipbook pages={pages} skin="light" /> // Light theme
721
+ <Flipbook pages={pages} skin="gradient" /> // Gradient theme
722
+ ```
723
+
724
+ ### CSS Custom Properties
725
+
726
+ ```css
727
+ .react-flipbook {
728
+ --flipbook-primary: #4a9eff;
729
+ --flipbook-background: #515558;
730
+ --flipbook-text: #ffffff;
731
+ --flipbook-btn-bg: rgba(255, 255, 255, 0.1);
732
+ --flipbook-btn-hover: rgba(255, 255, 255, 0.2);
733
+ --flipbook-sidebar-bg: #2a2a2a;
734
+ --flipbook-sidebar-width: 280px;
735
+ }
736
+ ```
737
+
738
+ ### CSS Classes
739
+
740
+ | Class | Description |
741
+ |-------|-------------|
742
+ | `.react-flipbook` | Main container |
743
+ | `.react-flipbook-container` | Book container |
744
+ | `.react-flipbook-book` | Book element |
745
+ | `.react-flipbook-pages` | Pages wrapper |
746
+ | `.react-flipbook-page` | Individual page |
747
+ | `.react-flipbook-menu` | Bottom toolbar |
748
+ | `.react-flipbook-btn` | Toolbar buttons |
749
+ | `.react-flipbook-nav-btn` | Side navigation buttons |
750
+ | `.react-flipbook-sidebar` | Side panels |
751
+ | `.react-flipbook-thumbnails` | Thumbnails grid |
752
+ | `.react-flipbook-toc` | Table of contents |
753
+ | `.react-flipbook-search` | Search panel |
754
+ | `.react-flipbook-bookmarks` | Bookmarks panel |
755
+ | `.react-flipbook-theme-dark` | Dark theme |
756
+ | `.react-flipbook-theme-light` | Light theme |
757
+ | `.react-flipbook-theme-gradient` | Gradient theme |
758
+
759
+ ---
760
+
761
+ ## Accessibility
762
+
763
+ ### Keyboard Shortcuts
764
+
765
+ | Key | Action |
766
+ |-----|--------|
767
+ | `←` / `ArrowLeft` | Previous page |
768
+ | `→` / `ArrowRight` | Next page |
769
+ | `Home` | First page |
770
+ | `End` | Last page |
771
+ | `+` / `=` | Zoom in |
772
+ | `-` | Zoom out |
773
+ | `0` | Reset zoom |
774
+ | `F` | Toggle fullscreen |
775
+ | `Escape` | Exit fullscreen |
776
+
777
+ ### ARIA Support
778
+
779
+ - Full keyboard navigation
780
+ - ARIA labels and roles on all interactive elements
781
+ - Screen reader announcements for page changes
782
+
783
+ ---
784
+
785
+ ## Utility Functions
786
+
787
+ ```tsx
788
+ import {
789
+ clamp,
790
+ lerp,
791
+ debounce,
792
+ throttle,
793
+ isMobile,
794
+ isTouchDevice,
795
+ isWebGLSupported,
796
+ preloadImage,
797
+ preloadImages,
798
+ generateId,
799
+ requestFullscreen,
800
+ exitFullscreen,
801
+ isFullscreen,
802
+ storage,
803
+ easing,
804
+ } from 'react-3d-flipbook';
805
+
806
+ // Clamp value between min and max
807
+ const clamped = clamp(value, 0, 100);
808
+
809
+ // Linear interpolation
810
+ const interpolated = lerp(start, end, 0.5);
811
+
812
+ // Debounce a function
813
+ const debouncedFn = debounce(fn, 300);
814
+
815
+ // Check device capabilities
816
+ if (isMobile()) { /* mobile device */ }
817
+ if (isTouchDevice()) { /* touch device */ }
818
+ if (isWebGLSupported()) { /* WebGL available */ }
819
+
820
+ // Preload images
821
+ await preloadImages(urls, (loaded, total) => {
822
+ console.log(`Loaded ${loaded}/${total}`);
823
+ });
824
+
825
+ // Local storage helpers
826
+ storage.set('key', value);
827
+ const value = storage.get('key', defaultValue);
828
+ storage.remove('key');
829
+
830
+ // Easing functions for animations
831
+ const easedValue = easing.easeInOutCubic(t);
832
+ const bounced = easing.easeOutQuart(t);
833
+ ```
834
+
835
+ ---
836
+
837
+ ## Browser Support
838
+
839
+ | Browser | Version | WebGL Support |
840
+ |---------|---------|---------------|
841
+ | Chrome | 80+ | ✅ |
842
+ | Firefox | 75+ | ✅ |
843
+ | Safari | 13+ | ✅ |
844
+ | Edge | 80+ | ✅ |
845
+ | iOS Safari | 13+ | ✅ |
846
+ | Android Chrome | 80+ | ✅ |
847
+
848
+ **Note:** WebGL is required for the 3D page-flip animations. The component displays a fallback message if WebGL is not available.
849
+
850
+ ---
851
+
852
+ ## Performance Tips
853
+
854
+ ### For Large PDFs
855
+
856
+ ```tsx
857
+ // Use lazy loading for large documents
858
+ const pages = [];
859
+ for await (const page of pdfToFlipbookPagesLazy(pdfUrl, {
860
+ scale: 1.5, // Lower scale = less memory
861
+ format: 'jpeg', // JPEG is smaller than PNG
862
+ quality: 0.8, // Lower quality = smaller files
863
+ })) {
864
+ pages.push(page);
865
+ setPages([...pages]); // Progressive loading
866
+ }
867
+ ```
868
+
869
+ ### Reduce Memory Usage
870
+
871
+ - Use `format: 'jpeg'` instead of `'png'`
872
+ - Lower `scale` value (1-1.5 instead of 2)
873
+ - Lower `quality` value (0.7-0.8)
874
+ - Use lazy loading with `pdfToFlipbookPagesLazy`
875
+
876
+ ### Improve Rendering Performance
877
+
878
+ - Disable shadows: `shadows={false}`
879
+ - Disable antialiasing: `antialias={false}`
880
+ - Reduce page segments: `pageSegmentsW={20}`
881
+
882
+ ---
883
+
884
+ ## TypeScript
885
+
886
+ Full TypeScript support with exported types:
887
+
888
+ ```tsx
889
+ import type {
890
+ // Page types
891
+ FlipbookPage,
892
+ TocItem,
893
+
894
+ // Component props
895
+ FlipbookProps,
896
+ FlipbookOptions,
897
+ WebGLPageFlipProps,
898
+
899
+ // Instance types
900
+ FlipbookInstance,
901
+ WebGLPageFlipInstance,
902
+
903
+ // Event types
904
+ FlipbookEventMap,
905
+
906
+ // Configuration types
907
+ SkinType,
908
+ ButtonConfig,
909
+ DownloadButtonConfig,
910
+ CurrentPageConfig,
911
+
912
+ // Hook types
913
+ UseAutoplayOptions,
914
+ UseAutoplayReturn,
915
+ UsePdfLoaderOptions,
916
+ UsePdfLoaderReturn,
917
+
918
+ // PDF utilities
919
+ PdfToImagesOptions,
920
+ PdfPageInfo,
921
+ FlipbookSizeOptions,
922
+ FlipbookSize,
923
+
924
+ // Panel types
925
+ SearchResult,
926
+ Bookmark,
927
+ } from 'react-3d-flipbook';
928
+ ```
929
+
930
+ ---
931
+
932
+ ## Troubleshooting
933
+
934
+ ### WebGL Issues
935
+
936
+ **Problem:** WebGL not working or blank screen
937
+ **Solution:** Ensure `three` is installed and browser supports WebGL. Check browser console for errors.
938
+
939
+ ### PDF Issues
940
+
941
+ **Problem:** PDF not loading
942
+ **Solution:**
943
+ 1. Ensure `pdfjs-dist` is installed
944
+ 2. Call `setPdfWorkerSrc()` before loading PDFs
945
+ 3. Check CORS settings if loading from external URLs
946
+
947
+ **Problem:** PDF pages are blurry
948
+ **Solution:** Increase `scale` option (e.g., `scale: 2` or `scale: 3`)
949
+
950
+ ### Performance Issues
951
+
952
+ **Problem:** Slow loading or high memory usage
953
+ **Solution:**
954
+ 1. Use `pdfToFlipbookPagesLazy` for progressive loading
955
+ 2. Lower `scale` and `quality` options
956
+ 3. Use JPEG format instead of PNG
957
+ 4. Disable shadows and reduce page segments
958
+
959
+ ### Animation Issues
960
+
961
+ **Problem:** Page flip animation is jerky
962
+ **Solution:**
963
+ 1. Reduce `pageSegmentsW` value
964
+ 2. Disable antialiasing if not needed
965
+ 3. Ensure consistent page aspect ratios
966
+
967
+ **Problem:** Pages don't align in two-page mode
968
+ **Solution:** Ensure all pages have consistent dimensions or let the library auto-size based on first page.
969
+
970
+ ---
971
+
972
+ ## Contributing
973
+
974
+ Contributions are welcome! Please fork, branch, and submit a PR.
975
+
976
+ 1. Fork the repository
977
+ 2. Create a feature branch: `git checkout -b feature/my-feature`
978
+ 3. Commit changes: `git commit -am 'Add new feature'`
979
+ 4. Push to branch: `git push origin feature/my-feature`
980
+ 5. Submit a Pull Request
981
+
982
+ ---
983
+
984
+ ## License
985
+
986
+ MIT License
987
+
988
+ ---
989
+
990
+ ## Changelog
991
+
992
+ ### v1.1.0
993
+ - Added automatic page sizing based on PDF dimensions
994
+ - Added `calculateFlipbookSize` and `calculateFlipbookSizeFromPages` utilities
995
+ - Improved camera positioning for better framing of content
996
+ - Fixed two-page spread alignment issues
997
+ - Improved support for landscape PDFs
998
+
999
+ ### v1.0.0
1000
+ - Initial release
1001
+ - WebGL 3D page flip animations
1002
+ - PDF support via PDF.js
1003
+ - Single-page and two-page spread modes
1004
+ - Thumbnails, TOC, Search, and Bookmarks panels
1005
+ - Multiple themes and full customization