@eternalheart/react-file-preview 1.4.0 → 1.5.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 +437 -60
- package/README.zh-CN.md +437 -60
- package/lib/FilePreviewContent.d.ts +1 -0
- package/lib/FilePreviewContent.d.ts.map +1 -1
- package/lib/FilePreviewEmbed.d.ts +2 -0
- package/lib/FilePreviewEmbed.d.ts.map +1 -1
- package/lib/FilePreviewModal.d.ts +2 -0
- package/lib/FilePreviewModal.d.ts.map +1 -1
- package/lib/chunks/index-BBYKNNLb.mjs +329 -0
- package/lib/chunks/index-BBYKNNLb.mjs.map +1 -0
- package/lib/chunks/index-BFh22D_W.mjs +78 -0
- package/lib/chunks/index-BFh22D_W.mjs.map +1 -0
- package/lib/chunks/{index-DoFsoBKL.mjs → index-BKXvtJh5.mjs} +27 -25
- package/lib/chunks/index-BKXvtJh5.mjs.map +1 -0
- package/lib/chunks/index-Bw3Fh4b5.mjs +116 -0
- package/lib/chunks/index-Bw3Fh4b5.mjs.map +1 -0
- package/lib/chunks/{index-kALp0tqz.mjs → index-CEC_DHgr.mjs} +22 -20
- package/lib/chunks/index-CEC_DHgr.mjs.map +1 -0
- package/lib/chunks/{index-CzM2mxrD.mjs → index-COOUxB5e.mjs} +130 -128
- package/lib/chunks/{index-CzM2mxrD.mjs.map → index-COOUxB5e.mjs.map} +1 -1
- package/lib/chunks/index-CU1Lc3lV.mjs +120 -0
- package/lib/chunks/index-CU1Lc3lV.mjs.map +1 -0
- package/lib/chunks/index-CgFv7B_G.mjs +359 -0
- package/lib/chunks/index-CgFv7B_G.mjs.map +1 -0
- package/lib/chunks/index-Cn4ZyhGM.mjs +587 -0
- package/lib/chunks/index-Cn4ZyhGM.mjs.map +1 -0
- package/lib/chunks/{index-DaAXRBWL.mjs → index-DGNNEnWE.mjs} +864 -862
- package/lib/chunks/{index-DaAXRBWL.mjs.map → index-DGNNEnWE.mjs.map} +1 -1
- package/lib/chunks/index-DLk08ylq.mjs +313 -0
- package/lib/chunks/index-DLk08ylq.mjs.map +1 -0
- package/lib/chunks/index-DVtPyN-s.mjs +200 -0
- package/lib/chunks/index-DVtPyN-s.mjs.map +1 -0
- package/lib/chunks/index-DreA69iU.mjs +2409 -0
- package/lib/chunks/index-DreA69iU.mjs.map +1 -0
- package/lib/chunks/{index-Cp68OevR.mjs → index-Dta7iGov.mjs} +1299 -1297
- package/lib/chunks/{index-Cp68OevR.mjs.map → index-Dta7iGov.mjs.map} +1 -1
- package/lib/chunks/index-fQGAUFAX.mjs +275 -0
- package/lib/chunks/index-fQGAUFAX.mjs.map +1 -0
- package/lib/chunks/{index-C_BJatqr.mjs → index-fSw6Hl5e.mjs} +42 -40
- package/lib/chunks/index-fSw6Hl5e.mjs.map +1 -0
- package/lib/chunks/index-jvNrkVkp.mjs +291 -0
- package/lib/chunks/index-jvNrkVkp.mjs.map +1 -0
- package/lib/chunks/index-oVJyD-FV.mjs +107 -0
- package/lib/chunks/index-oVJyD-FV.mjs.map +1 -0
- package/lib/chunks/{index-DuP0Tlpo.mjs → index-vRLKumL8.mjs} +43 -41
- package/lib/chunks/index-vRLKumL8.mjs.map +1 -0
- package/lib/chunks/useShikiHighlight-C6nJcETW.mjs +36 -0
- package/lib/chunks/useShikiHighlight-C6nJcETW.mjs.map +1 -0
- package/lib/components/preview/FilePreviewToolbar.d.ts +1 -0
- package/lib/components/preview/FilePreviewToolbar.d.ts.map +1 -1
- package/lib/components/preview/ToolbarButton.d.ts +3 -1
- package/lib/components/preview/ToolbarButton.d.ts.map +1 -1
- package/lib/hooks/index.d.ts +0 -6
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/useShikiHighlight.d.ts +3 -1
- package/lib/hooks/useShikiHighlight.d.ts.map +1 -1
- package/lib/index.cjs +32 -30
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +1 -1
- package/lib/renderers/Audio/index.d.ts +2 -1
- package/lib/renderers/Audio/index.d.ts.map +1 -1
- package/lib/renderers/Csv/index.d.ts +2 -1
- package/lib/renderers/Csv/index.d.ts.map +1 -1
- package/lib/renderers/Docx/index.d.ts +2 -1
- package/lib/renderers/Docx/index.d.ts.map +1 -1
- package/lib/renderers/Epub/index.d.ts +2 -3
- package/lib/renderers/Epub/index.d.ts.map +1 -1
- package/lib/renderers/Font/index.d.ts +2 -1
- package/lib/renderers/Font/index.d.ts.map +1 -1
- package/lib/renderers/Image/index.d.ts +6 -7
- package/lib/renderers/Image/index.d.ts.map +1 -1
- package/lib/renderers/Json/index.d.ts +2 -1
- package/lib/renderers/Json/index.d.ts.map +1 -1
- package/lib/renderers/Markdown/index.d.ts +2 -2
- package/lib/renderers/Markdown/index.d.ts.map +1 -1
- package/lib/renderers/Mobi/index.d.ts +2 -3
- package/lib/renderers/Mobi/index.d.ts.map +1 -1
- package/lib/renderers/Msg/index.d.ts +2 -1
- package/lib/renderers/Msg/index.d.ts.map +1 -1
- package/lib/renderers/Pdf/index.d.ts +4 -8
- package/lib/renderers/Pdf/index.d.ts.map +1 -1
- package/lib/renderers/Pptx/index.d.ts +2 -1
- package/lib/renderers/Pptx/index.d.ts.map +1 -1
- package/lib/renderers/Subtitle/index.d.ts +2 -1
- package/lib/renderers/Subtitle/index.d.ts.map +1 -1
- package/lib/renderers/Text/index.d.ts +2 -3
- package/lib/renderers/Text/index.d.ts.map +1 -1
- package/lib/renderers/Video/index.d.ts +2 -1
- package/lib/renderers/Video/index.d.ts.map +1 -1
- package/lib/renderers/Xlsx/index.d.ts +2 -1
- package/lib/renderers/Xlsx/index.d.ts.map +1 -1
- package/lib/renderers/Xml/index.d.ts +2 -1
- package/lib/renderers/Xml/index.d.ts.map +1 -1
- package/lib/renderers/Zip/index.d.ts +7 -2
- package/lib/renderers/Zip/index.d.ts.map +1 -1
- package/lib/renderers/base.types.d.ts +38 -0
- package/lib/renderers/base.types.d.ts.map +1 -0
- package/lib/renderers/registry.d.ts +36 -0
- package/lib/renderers/registry.d.ts.map +1 -0
- package/lib/renderers/toolbar.types.d.ts +2 -0
- package/lib/renderers/toolbar.types.d.ts.map +1 -1
- package/lib/toolbar/renderItems.d.ts.map +1 -1
- package/package.json +3 -3
- package/lib/chunks/index-0v5STX5f.mjs +0 -105
- package/lib/chunks/index-0v5STX5f.mjs.map +0 -1
- package/lib/chunks/index-10O8tfTH.mjs +0 -529
- package/lib/chunks/index-10O8tfTH.mjs.map +0 -1
- package/lib/chunks/index-BCyv1HM9.mjs +0 -175
- package/lib/chunks/index-BCyv1HM9.mjs.map +0 -1
- package/lib/chunks/index-Bo90aGhy.mjs +0 -114
- package/lib/chunks/index-Bo90aGhy.mjs.map +0 -1
- package/lib/chunks/index-CEeKt7L3.mjs +0 -2808
- package/lib/chunks/index-CEeKt7L3.mjs.map +0 -1
- package/lib/chunks/index-CWKbnvW6.mjs +0 -270
- package/lib/chunks/index-CWKbnvW6.mjs.map +0 -1
- package/lib/chunks/index-C_BJatqr.mjs.map +0 -1
- package/lib/chunks/index-Cbz5Z6ZK.mjs +0 -263
- package/lib/chunks/index-Cbz5Z6ZK.mjs.map +0 -1
- package/lib/chunks/index-DTYBFuAH.mjs +0 -357
- package/lib/chunks/index-DTYBFuAH.mjs.map +0 -1
- package/lib/chunks/index-DoFsoBKL.mjs.map +0 -1
- package/lib/chunks/index-DuP0Tlpo.mjs.map +0 -1
- package/lib/chunks/index-Dv3RQz86.mjs +0 -270
- package/lib/chunks/index-Dv3RQz86.mjs.map +0 -1
- package/lib/chunks/index-QfpHck8N.mjs +0 -55
- package/lib/chunks/index-QfpHck8N.mjs.map +0 -1
- package/lib/chunks/index-gjSQeou7.mjs +0 -194
- package/lib/chunks/index-gjSQeou7.mjs.map +0 -1
- package/lib/chunks/index-kALp0tqz.mjs.map +0 -1
- package/lib/chunks/index-kCeSnFs-.mjs +0 -54
- package/lib/chunks/index-kCeSnFs-.mjs.map +0 -1
- package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs +0 -23
- package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs.map +0 -1
- package/lib/hooks/rendererReducer.d.ts +0 -10
- package/lib/hooks/rendererReducer.d.ts.map +0 -1
- package/lib/hooks/types.d.ts +0 -152
- package/lib/hooks/types.d.ts.map +0 -1
- package/lib/hooks/useBookRenderer.d.ts +0 -14
- package/lib/hooks/useBookRenderer.d.ts.map +0 -1
- package/lib/hooks/useFilePreviewState.d.ts +0 -10
- package/lib/hooks/useFilePreviewState.d.ts.map +0 -1
- package/lib/hooks/useImageAutoFit.d.ts +0 -13
- package/lib/hooks/useImageAutoFit.d.ts.map +0 -1
- package/lib/hooks/useToolbarConfig.d.ts +0 -25
- package/lib/hooks/useToolbarConfig.d.ts.map +0 -1
- package/lib/renderers/Epub/toolbar.d.ts +0 -13
- package/lib/renderers/Epub/toolbar.d.ts.map +0 -1
- package/lib/renderers/Image/toolbar.d.ts +0 -15
- package/lib/renderers/Image/toolbar.d.ts.map +0 -1
- package/lib/renderers/Markdown/toolbar.d.ts +0 -9
- package/lib/renderers/Markdown/toolbar.d.ts.map +0 -1
- package/lib/renderers/Mobi/toolbar.d.ts +0 -13
- package/lib/renderers/Mobi/toolbar.d.ts.map +0 -1
- package/lib/renderers/Pdf/toolbar.d.ts +0 -16
- package/lib/renderers/Pdf/toolbar.d.ts.map +0 -1
- package/lib/renderers/Text/toolbar.d.ts +0 -12
- package/lib/renderers/Text/toolbar.d.ts.map +0 -1
- package/lib/renderers/Zip/toolbar.d.ts +0 -13
- package/lib/renderers/Zip/toolbar.d.ts.map +0 -1
- package/lib/toolbar/registry.d.ts +0 -51
- package/lib/toolbar/registry.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -6,24 +6,23 @@ A modern, feature-rich file preview component for React with support for images,
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
## ✨ Features
|
|
10
|
-
|
|
11
|
-
- 🎨 **Modern UI** -
|
|
12
|
-
- 📁 **Multi-format Support** - Supports 20+ file formats
|
|
13
|
-
- 🪟 **Two Display Modes** - Full-screen modal **or** inline embedded preview
|
|
14
|
-
- 🖼️ **Powerful Image Viewer** - Zoom, rotate, drag, mouse wheel zoom
|
|
15
|
-
- 🎬 **Custom Video Player** - Built on Video.js, supports multiple video formats
|
|
16
|
-
- 🎵 **Custom Audio Player** - Beautiful audio control interface
|
|
17
|
-
- 📄 **PDF Viewer** - Pagination support
|
|
18
|
-
- 📊 **Office Documents Support** - Word, Excel, PowerPoint file preview
|
|
19
|
-
- 📝 **Markdown Rendering** - GitHub Flavored Markdown support
|
|
20
|
-
- 💻 **Code Highlighting** - Supports 40+ programming languages
|
|
21
|
-
- 🎭 **Smooth Animations** - Powered by Framer Motion
|
|
22
|
-
- 📱 **Responsive Design** - Adapts to all screen sizes
|
|
23
|
-
- ⌨️ **Keyboard Navigation** - Arrow keys and ESC support
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## 📦 Installation
|
|
9
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/2728.svg" width="20" height="20" alt="✨" /> Features
|
|
10
|
+
|
|
11
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3a8.svg" width="16" height="16" alt="🎨" style="vertical-align: middle;" /> **Modern UI** - Clean and modern interface with smooth animations
|
|
12
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4c1.svg" width="16" height="16" alt="📁" style="vertical-align: middle;" /> **Multi-format Support** - Supports 20+ file formats
|
|
13
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1fa9f.svg" width="16" height="16" alt="🪟" style="vertical-align: middle;" /> **Two Display Modes** - Full-screen modal **or** inline embedded preview
|
|
14
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f5bc.svg" width="16" height="16" alt="🖼️" style="vertical-align: middle;" /> **Powerful Image Viewer** - Zoom, rotate, drag, mouse wheel zoom
|
|
15
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3ac.svg" width="16" height="16" alt="🎬" style="vertical-align: middle;" /> **Custom Video Player** - Built on Video.js, supports multiple video formats
|
|
16
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3b5.svg" width="16" height="16" alt="🎵" style="vertical-align: middle;" /> **Custom Audio Player** - Beautiful audio control interface
|
|
17
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4c4.svg" width="16" height="16" alt="📄" style="vertical-align: middle;" /> **PDF Viewer** - Pagination support
|
|
18
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4ca.svg" width="16" height="16" alt="📊" style="vertical-align: middle;" /> **Office Documents Support** - Word, Excel, PowerPoint file preview
|
|
19
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4dd.svg" width="16" height="16" alt="📝" style="vertical-align: middle;" /> **Markdown Rendering** - GitHub Flavored Markdown support
|
|
20
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4bb.svg" width="16" height="16" alt="💻" style="vertical-align: middle;" /> **Code Highlighting** - Supports 40+ programming languages
|
|
21
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3ad.svg" width="16" height="16" alt="🎭" style="vertical-align: middle;" /> **Smooth Animations** - Powered by Framer Motion
|
|
22
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4f1.svg" width="16" height="16" alt="📱" style="vertical-align: middle;" /> **Responsive Design** - Adapts to all screen sizes
|
|
23
|
+
- <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/2328.svg" width="16" height="16" alt="⌨️" style="vertical-align: middle;" /> **Keyboard Navigation** - Arrow keys and ESC support
|
|
24
|
+
|
|
25
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4e6.svg" width="20" height="20" alt="📦" /> Installation
|
|
27
26
|
|
|
28
27
|
```bash
|
|
29
28
|
# Using npm
|
|
@@ -138,7 +137,7 @@ export default defineConfig({
|
|
|
138
137
|
|
|
139
138
|
> Note: `@jsquash/avif` is only used as a fallback when the browser does not natively support AVIF (Chrome 85+, Firefox 93+, Safari 16+ all support it natively). If your target browsers cover the native list, you can also remove `@jsquash/avif` from your dependencies entirely.
|
|
140
139
|
|
|
141
|
-
## 🚀 Quick Start
|
|
140
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f680.svg" width="20" height="20" alt="🚀" /> Quick Start
|
|
142
141
|
|
|
143
142
|
📖 **New to this library?** Check out the [Quick Start Guide](./QUICK_START.md) for a 5-minute introduction!
|
|
144
143
|
|
|
@@ -189,14 +188,18 @@ import { FilePreviewModal, PreviewFileInput } from '@eternalheart/react-file-pre
|
|
|
189
188
|
import '@eternalheart/react-file-preview/style.css';
|
|
190
189
|
|
|
191
190
|
function App() {
|
|
191
|
+
// Assume `file1` comes from a File API source: <input type="file">,
|
|
192
|
+
// drag & drop, clipboard paste, or fetch().then(r => r.blob())
|
|
193
|
+
const file1 = new File(['content'], 'example.txt', { type: 'text/plain' });
|
|
194
|
+
|
|
192
195
|
const files: PreviewFileInput[] = [
|
|
193
|
-
// 1. Native File object
|
|
196
|
+
// 1. Native File object (auto revoked when unmounted)
|
|
194
197
|
file1,
|
|
195
198
|
|
|
196
|
-
// 2. HTTP URL string
|
|
199
|
+
// 2. HTTP URL string (loaded on demand)
|
|
197
200
|
'https://example.com/image.jpg',
|
|
198
201
|
|
|
199
|
-
// 3. File object with metadata
|
|
202
|
+
// 3. File object with metadata (recommended for remote resources)
|
|
200
203
|
{
|
|
201
204
|
name: 'document.pdf',
|
|
202
205
|
type: 'application/pdf',
|
|
@@ -205,6 +208,9 @@ function App() {
|
|
|
205
208
|
},
|
|
206
209
|
];
|
|
207
210
|
|
|
211
|
+
// Memory note: If you generate URLs via URL.createObjectURL(),
|
|
212
|
+
// call URL.revokeObjectURL() when files are removed to avoid memory leaks.
|
|
213
|
+
|
|
208
214
|
return (
|
|
209
215
|
<FilePreviewModal
|
|
210
216
|
files={files}
|
|
@@ -258,7 +264,7 @@ Differences from `FilePreviewModal`:
|
|
|
258
264
|
<FilePreviewEmbed files={files} width={800} height={500} />
|
|
259
265
|
```
|
|
260
266
|
|
|
261
|
-
## 💡 Usage Examples
|
|
267
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4a1.svg" width="20" height="20" alt="💡" /> Usage Examples
|
|
262
268
|
|
|
263
269
|
### Preview PowerPoint Files
|
|
264
270
|
|
|
@@ -311,7 +317,7 @@ const files = [
|
|
|
311
317
|
/>
|
|
312
318
|
```
|
|
313
319
|
|
|
314
|
-
## 📖 Supported File Formats
|
|
320
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4d6.svg" width="20" height="20" alt="📖" /> Supported File Formats
|
|
315
321
|
|
|
316
322
|
### Images
|
|
317
323
|
- **Formats**: JPG, PNG, GIF, WebP, SVG, BMP, ICO
|
|
@@ -360,7 +366,56 @@ const files = [
|
|
|
360
366
|
### E-books
|
|
361
367
|
- **EPUB**: Chapter navigation, pagination
|
|
362
368
|
|
|
363
|
-
##
|
|
369
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/26a0.svg" width="20" height="20" alt="⚠️" /> Limitations & Performance
|
|
370
|
+
|
|
371
|
+
### Support Levels
|
|
372
|
+
|
|
373
|
+
**✅ Full Support (Production Ready)**
|
|
374
|
+
- Images (JPG, PNG, GIF, WebP, SVG, BMP, ICO)
|
|
375
|
+
- Videos (MP4, WebM, OGG)
|
|
376
|
+
- Audio (MP3, WAV, OGG)
|
|
377
|
+
- PDF
|
|
378
|
+
- Markdown
|
|
379
|
+
- Code files (40+ languages via Shiki, lazy-loaded)
|
|
380
|
+
- JSON, CSV, XML
|
|
381
|
+
|
|
382
|
+
**⚠️ Partial Support (Preview Only)**
|
|
383
|
+
- **Office (DOCX, XLSX, PPTX)**: Basic layout and text rendering. Complex formatting (charts, macros, embedded objects) may not render accurately.
|
|
384
|
+
- **ZIP**: Directory tree browsing + inline preview for text/code/images. Large archives (>100MB) may cause performance issues.
|
|
385
|
+
- **Fonts (TTF, OTF, WOFF)**: Metadata + character preview. Full font feature testing not supported.
|
|
386
|
+
|
|
387
|
+
**🧪 Experimental**
|
|
388
|
+
- **MSG (Outlook Email)**: Headers and plain text body. Complex HTML body may not render correctly.
|
|
389
|
+
- **EPUB**: Basic chapter navigation. CSS styling may differ from native readers. DRM-protected files not supported.
|
|
390
|
+
- **Subtitle formats (SRT, ASS, TTML, LRC)**: Text display only. No video sync or advanced styling.
|
|
391
|
+
|
|
392
|
+
### Performance Boundaries
|
|
393
|
+
|
|
394
|
+
| File Size | Status | Notes |
|
|
395
|
+
|-----------|--------|-------|
|
|
396
|
+
| < 50MB | ✅ Recommended | Smooth preview experience |
|
|
397
|
+
| 50-100MB | ⚠️ May lag | UI may become unresponsive during load |
|
|
398
|
+
| > 100MB | ❌ Not recommended | Browser memory limits may be exceeded |
|
|
399
|
+
|
|
400
|
+
**Special Cases:**
|
|
401
|
+
- **ZIP archives**: Performance depends on file count, not just size
|
|
402
|
+
- **Office documents**: Complex files (>200 pages, heavy images) may timeout
|
|
403
|
+
- **Code highlighting**: Files >5MB may take 3-5s to highlight
|
|
404
|
+
|
|
405
|
+
### Browser Compatibility
|
|
406
|
+
|
|
407
|
+
**Minimum Requirements:**
|
|
408
|
+
- Chrome 90+ / Edge 90+
|
|
409
|
+
- Firefox 88+
|
|
410
|
+
- Safari 14+
|
|
411
|
+
|
|
412
|
+
**Known Limitations:**
|
|
413
|
+
- **Safari iOS**: Video autoplay requires user interaction
|
|
414
|
+
- **Firefox**: AVIF support requires Firefox 93+ (fallback decoder included)
|
|
415
|
+
- **Office formats**: Rendering quality varies across browsers
|
|
416
|
+
- **EPUB**: Some CSS features unsupported in older browsers
|
|
417
|
+
|
|
418
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3ae.svg" width="20" height="20" alt="🎮" /> API Reference
|
|
364
419
|
|
|
365
420
|
### FilePreviewModal Props
|
|
366
421
|
|
|
@@ -376,6 +431,7 @@ const files = [
|
|
|
376
431
|
| `messages` | `Partial<Record<Locale, Partial<Messages>>>` | ❌ | Custom translation overrides |
|
|
377
432
|
| `headless` | `boolean` | ❌ | Headless mode — hides toolbar and navigation arrows |
|
|
378
433
|
| `theme` | `Theme` | ❌ | Theme mode: `'auto' \| 'dark' \| 'light'` (default `'dark'`) |
|
|
434
|
+
| `showDownload` | `boolean` | ❌ | Whether to show the download button (default `true`) |
|
|
379
435
|
|
|
380
436
|
### FilePreviewEmbed Props
|
|
381
437
|
|
|
@@ -393,6 +449,7 @@ const files = [
|
|
|
393
449
|
| `messages` | `Partial<Record<Locale, Partial<Messages>>>` | ❌ | - | Custom translation overrides |
|
|
394
450
|
| `headless` | `boolean` | ❌ | `false` | Headless mode — hides toolbar and navigation arrows |
|
|
395
451
|
| `theme` | `Theme` | ❌ | `'dark'` | Theme mode: `'auto' \| 'dark' \| 'light'` |
|
|
452
|
+
| `showDownload` | `boolean` | ❌ | `true` | Whether to show the download button |
|
|
396
453
|
|
|
397
454
|
> `FilePreviewEmbed` has no `isOpen` / `onClose`. To hide/show it, conditionally render it from the parent. It also hides the close button in the toolbar.
|
|
398
455
|
|
|
@@ -512,7 +569,7 @@ const files = [
|
|
|
512
569
|
#### E-books
|
|
513
570
|
- **EPUB**: `application/epub+zip` (.epub)
|
|
514
571
|
|
|
515
|
-
## 🌐 Internationalization (i18n)
|
|
572
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f310.svg" width="20" height="20" alt="🌐" /> Internationalization (i18n)
|
|
516
573
|
|
|
517
574
|
Built-in support for Chinese (default) and English. Zero external dependencies.
|
|
518
575
|
|
|
@@ -530,7 +587,353 @@ Built-in support for Chinese (default) and English. Zero external dependencies.
|
|
|
530
587
|
|
|
531
588
|
Use `useTranslator()` hook in custom renderers to access the translation function.
|
|
532
589
|
|
|
533
|
-
##
|
|
590
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f9e9.svg" width="20" height="20" alt="🧩" /> Custom Renderers
|
|
591
|
+
|
|
592
|
+
The library supports custom renderers for handling file types not built-in. Custom renderers can optionally provide toolbar configurations and integrate with the library's architecture.
|
|
593
|
+
|
|
594
|
+
### Event-Driven Toolbar Updates
|
|
595
|
+
|
|
596
|
+
Custom renderers can implement real-time toolbar updates using the event-driven mechanism:
|
|
597
|
+
|
|
598
|
+
**Benefits:**
|
|
599
|
+
- **Real-time updates**: Toolbar reflects state changes immediately
|
|
600
|
+
- **Better performance**: No polling overhead or unnecessary re-renders
|
|
601
|
+
- **Type-safe**: Full TypeScript support with proper interfaces
|
|
602
|
+
|
|
603
|
+
**Implementation:**
|
|
604
|
+
|
|
605
|
+
```tsx
|
|
606
|
+
import { forwardRef, useImperativeHandle, useState, useEffect, useMemo, useCallback } from 'react';
|
|
607
|
+
import { ToolbarEventEmitter } from '@eternalheart/react-file-preview';
|
|
608
|
+
import type { RendererHandle, ToolbarGroup } from '@eternalheart/react-file-preview';
|
|
609
|
+
|
|
610
|
+
interface CustomRendererProps {
|
|
611
|
+
url: string;
|
|
612
|
+
onPageChange?: (current: number, total: number) => void;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export const CustomRenderer = forwardRef<RendererHandle, CustomRendererProps>((props, ref) => {
|
|
616
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
617
|
+
const [totalPages, setTotalPages] = useState(10);
|
|
618
|
+
const emitter = useMemo(() => new ToolbarEventEmitter(), []);
|
|
619
|
+
|
|
620
|
+
// Notify toolbar when state changes
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
emitter.notify();
|
|
623
|
+
props.onPageChange?.(currentPage, totalPages);
|
|
624
|
+
}, [currentPage, totalPages, emitter, props]);
|
|
625
|
+
|
|
626
|
+
const getToolbarGroups = useCallback((): ToolbarGroup[] => [
|
|
627
|
+
{
|
|
628
|
+
items: [
|
|
629
|
+
{
|
|
630
|
+
type: 'button',
|
|
631
|
+
icon: <ChevronLeft className="w-4 h-4" />,
|
|
632
|
+
tooltip: 'Previous Page',
|
|
633
|
+
action: () => setCurrentPage(p => Math.max(1, p - 1)),
|
|
634
|
+
disabled: currentPage <= 1
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
type: 'text',
|
|
638
|
+
content: `${currentPage} / ${totalPages}`,
|
|
639
|
+
minWidth: '4rem'
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
type: 'button',
|
|
643
|
+
icon: <ChevronRight className="w-4 h-4" />,
|
|
644
|
+
tooltip: 'Next Page',
|
|
645
|
+
action: () => setCurrentPage(p => Math.min(totalPages, p + 1)),
|
|
646
|
+
disabled: currentPage >= totalPages
|
|
647
|
+
}
|
|
648
|
+
]
|
|
649
|
+
}
|
|
650
|
+
], [currentPage, totalPages]);
|
|
651
|
+
|
|
652
|
+
useImperativeHandle(ref, () => ({
|
|
653
|
+
getToolbarGroups,
|
|
654
|
+
onToolbarChange: (listener) => emitter.subscribe(listener)
|
|
655
|
+
}), [getToolbarGroups, emitter]);
|
|
656
|
+
|
|
657
|
+
return <div>Your custom renderer UI</div>;
|
|
658
|
+
});
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Main component usage:**
|
|
662
|
+
|
|
663
|
+
```tsx
|
|
664
|
+
import { CustomRenderer } from './CustomRenderer';
|
|
665
|
+
|
|
666
|
+
<FilePreviewModal
|
|
667
|
+
files={files}
|
|
668
|
+
customRenderers={[
|
|
669
|
+
{
|
|
670
|
+
test: (file) => file.type === 'application/custom',
|
|
671
|
+
component: CustomRenderer
|
|
672
|
+
}
|
|
673
|
+
]}
|
|
674
|
+
/>
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
The main component automatically detects `onToolbarChange` and subscribes to events. If not implemented, it falls back to polling for backward compatibility.
|
|
678
|
+
|
|
679
|
+
### Renderer Lazy Loading
|
|
680
|
+
|
|
681
|
+
All built-in renderers use code-splitting via `React.lazy` to minimize the main bundle size and improve initial load performance.
|
|
682
|
+
|
|
683
|
+
**Architecture:**
|
|
684
|
+
|
|
685
|
+
- **Registration**: Renderers register in `src/renderers/lazy.tsx` using named exports wrapped in `React.lazy`
|
|
686
|
+
- **Loading**: Each renderer is a separate chunk, loaded on-demand when needed
|
|
687
|
+
- **Fallback**: `<Suspense>` with `<RendererLoading />` handles the loading state
|
|
688
|
+
|
|
689
|
+
**Bundle Size Impact:**
|
|
690
|
+
|
|
691
|
+
- Main entry point: gzip ≤ 80 KB (strictly enforced by CI)
|
|
692
|
+
- Each renderer: separate async chunk
|
|
693
|
+
- Total library: gzip ≤ 800 KB (all renderers combined)
|
|
694
|
+
|
|
695
|
+
**Implementation Example:**
|
|
696
|
+
|
|
697
|
+
```tsx
|
|
698
|
+
// src/renderers/lazy.tsx
|
|
699
|
+
import { lazy } from 'react';
|
|
700
|
+
import type { CustomRenderer as CustomRendererImpl } from './Custom';
|
|
701
|
+
|
|
702
|
+
export const CustomRenderer: Lazy<typeof CustomRendererImpl> = lazy(() =>
|
|
703
|
+
import('./Custom').then((m) => ({ default: m.CustomRenderer }))
|
|
704
|
+
);
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
```tsx
|
|
708
|
+
// src/FilePreviewContent.tsx
|
|
709
|
+
import { CustomRenderer } from './renderers/lazy'; // ✅ Lazy import
|
|
710
|
+
// NOT: import { CustomRenderer } from './renderers/Custom'; // ❌ Direct import breaks code-splitting
|
|
711
|
+
|
|
712
|
+
<Suspense fallback={<RendererLoading />}>
|
|
713
|
+
{fileType === 'custom' && <CustomRenderer ref={rendererRef} url={currentFile.url} />}
|
|
714
|
+
</Suspense>
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
**For Custom Renderers:**
|
|
718
|
+
|
|
719
|
+
If you want your custom renderer to benefit from code-splitting, you can use the same pattern:
|
|
720
|
+
|
|
721
|
+
```tsx
|
|
722
|
+
import { lazy, Suspense } from 'react';
|
|
723
|
+
|
|
724
|
+
const MyCustomRenderer = lazy(() => import('./MyCustomRenderer'));
|
|
725
|
+
|
|
726
|
+
<FilePreviewModal
|
|
727
|
+
files={files}
|
|
728
|
+
customRenderers={[
|
|
729
|
+
{
|
|
730
|
+
test: (file) => file.type === 'application/custom',
|
|
731
|
+
component: (props) => (
|
|
732
|
+
<Suspense fallback={<div>Loading...</div>}>
|
|
733
|
+
<MyCustomRenderer {...props} />
|
|
734
|
+
</Suspense>
|
|
735
|
+
)
|
|
736
|
+
}
|
|
737
|
+
]}
|
|
738
|
+
/>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### i18n Integration
|
|
742
|
+
|
|
743
|
+
Custom renderers can access the library's i18n system via the `useTranslator()` hook for consistent multilingual support.
|
|
744
|
+
|
|
745
|
+
**Architecture:**
|
|
746
|
+
|
|
747
|
+
- **Dictionary Source**: `file-preview-core/src/i18n/messages/` (zh-CN.ts, en-US.ts)
|
|
748
|
+
- **No Hardcoding**: All user-visible text must use translation keys
|
|
749
|
+
- **Automatic Locale Switching**: Follows the `locale` prop passed to `FilePreviewModal`
|
|
750
|
+
|
|
751
|
+
**Usage in Custom Renderers:**
|
|
752
|
+
|
|
753
|
+
```tsx
|
|
754
|
+
import { useTranslator } from '@eternalheart/react-file-preview';
|
|
755
|
+
|
|
756
|
+
export const CustomRenderer = forwardRef<RendererHandle, Props>((props, ref) => {
|
|
757
|
+
const t = useTranslator();
|
|
758
|
+
const [error, setError] = useState<string | null>(null);
|
|
759
|
+
|
|
760
|
+
if (error) {
|
|
761
|
+
return (
|
|
762
|
+
<div className="rfp-text-fg-primary">
|
|
763
|
+
{t('custom.load_failed')}: {error}
|
|
764
|
+
</div>
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return (
|
|
769
|
+
<div>
|
|
770
|
+
<button>{t('common.download')}</button>
|
|
771
|
+
<span>{t('custom.loading')}</span>
|
|
772
|
+
</div>
|
|
773
|
+
);
|
|
774
|
+
});
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
**Adding Custom Translation Keys:**
|
|
778
|
+
|
|
779
|
+
For custom renderers, extend translations via the `messages` prop (do NOT modify source files in `node_modules`):
|
|
780
|
+
|
|
781
|
+
```tsx
|
|
782
|
+
<FilePreviewModal
|
|
783
|
+
files={files}
|
|
784
|
+
locale="en-US"
|
|
785
|
+
messages={{
|
|
786
|
+
'en-US': {
|
|
787
|
+
'custom.load_failed': 'Failed to load custom file',
|
|
788
|
+
'custom.file_size': 'File size: {size} KB'
|
|
789
|
+
},
|
|
790
|
+
'zh-CN': {
|
|
791
|
+
'custom.load_failed': '自定义文件加载失败',
|
|
792
|
+
'custom.file_size': '文件大小: {size} KB'
|
|
793
|
+
}
|
|
794
|
+
}}
|
|
795
|
+
customRenderers={[...]}
|
|
796
|
+
/>
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
**Guidelines:**
|
|
800
|
+
- Use `<scope>.<snake_name>` format (e.g., `custom.load_failed`, `custom.parse_error`)
|
|
801
|
+
- Provide translations for all enabled locales (`zh-CN` and `en-US`)
|
|
802
|
+
- Common keys already available: `common.loading`, `common.download`, `common.close`, `toolbar.*`
|
|
803
|
+
|
|
804
|
+
**Parameterized Translations:**
|
|
805
|
+
|
|
806
|
+
```tsx
|
|
807
|
+
// Dictionary: 'custom.file_size': '文件大小: {size} KB'
|
|
808
|
+
t('custom.file_size', { size: 1024 }) // → "文件大小: 1024 KB"
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
**Toolbar Integration:**
|
|
812
|
+
|
|
813
|
+
Toolbar items should also use translated strings:
|
|
814
|
+
|
|
815
|
+
```tsx
|
|
816
|
+
const getToolbarGroups = useCallback((): ToolbarGroup[] => [
|
|
817
|
+
{
|
|
818
|
+
items: [
|
|
819
|
+
{
|
|
820
|
+
type: 'button',
|
|
821
|
+
icon: <Download className="rfp-w-4 rfp-h-4" />,
|
|
822
|
+
tooltip: t('common.download'), // ✅ Translated
|
|
823
|
+
action: handleDownload
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
}
|
|
827
|
+
], [t]);
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
### Theme Adaptation
|
|
831
|
+
|
|
832
|
+
Custom renderers must use semantic color tokens to support the library's `'auto' | 'dark' | 'light'` theme system.
|
|
833
|
+
|
|
834
|
+
**Semantic Token System:**
|
|
835
|
+
|
|
836
|
+
All colors are defined as CSS variables (`--fp-*`) and exposed via Tailwind classes with the `rfp-` prefix:
|
|
837
|
+
|
|
838
|
+
| Usage | Class | Description |
|
|
839
|
+
|-------|-------|-------------|
|
|
840
|
+
| **Text (fg)** | | |
|
|
841
|
+
| Primary text | `rfp-text-fg-primary` | Highest contrast |
|
|
842
|
+
| Body text | `rfp-text-fg-secondary` | Default text |
|
|
843
|
+
| Secondary text | `rfp-text-fg-tertiary` | Captions, counters |
|
|
844
|
+
| Muted text | `rfp-text-fg-muted` | Placeholders |
|
|
845
|
+
| Disabled text | `rfp-text-fg-disabled` | Disabled buttons |
|
|
846
|
+
| **Background (surface)** | | |
|
|
847
|
+
| Surface 1 | `rfp-bg-surface-1` | Cards, weakest |
|
|
848
|
+
| Surface 2 | `rfp-bg-surface-2` | Hover states |
|
|
849
|
+
| Surface 3 | `rfp-bg-surface-3` | Emphasis |
|
|
850
|
+
| Toolbar | `rfp-bg-surface-toolbar` | Top toolbar |
|
|
851
|
+
| **Borders** | | |
|
|
852
|
+
| Weak border | `rfp-border-line-weak` | Subtle lines |
|
|
853
|
+
| Standard border | `rfp-border-line` | Default borders |
|
|
854
|
+
| Strong border | `rfp-border-line-strong` | Emphasis |
|
|
855
|
+
| **Code** | | |
|
|
856
|
+
| Code background | `rfp-bg-code-bg` | Dark: #1e1e1e / Light: #f6f8fa |
|
|
857
|
+
| Code text | `rfp-text-code-fg` | Follows theme |
|
|
858
|
+
| **Accent** | | |
|
|
859
|
+
| Accent background | `rfp-bg-accent` | Primary buttons |
|
|
860
|
+
| Accent hover | `rfp-bg-accent-hover` | Hover state |
|
|
861
|
+
|
|
862
|
+
**✅ Correct Usage:**
|
|
863
|
+
|
|
864
|
+
```tsx
|
|
865
|
+
export const CustomRenderer = forwardRef<RendererHandle, Props>((props, ref) => {
|
|
866
|
+
return (
|
|
867
|
+
<div className="rfp-bg-surface-1 rfp-border rfp-border-line-weak rfp-rounded">
|
|
868
|
+
<h2 className="rfp-text-fg-primary rfp-text-lg">Title</h2>
|
|
869
|
+
<p className="rfp-text-fg-secondary">Body text</p>
|
|
870
|
+
<button className="rfp-bg-surface-2 hover:rfp-bg-surface-3 rfp-text-fg-primary">
|
|
871
|
+
Click me
|
|
872
|
+
</button>
|
|
873
|
+
<pre className="rfp-bg-code-bg rfp-text-code-fg">
|
|
874
|
+
{code}
|
|
875
|
+
</pre>
|
|
876
|
+
</div>
|
|
877
|
+
);
|
|
878
|
+
});
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
**❌ Incorrect Usage (DO NOT USE):**
|
|
882
|
+
|
|
883
|
+
```tsx
|
|
884
|
+
// ❌ Literal color classes — breaks theme switching
|
|
885
|
+
<div className="rfp-text-white/90 rfp-bg-white/10 rfp-border-white/15">
|
|
886
|
+
<div className="rfp-text-gray-700 rfp-bg-gray-100">
|
|
887
|
+
|
|
888
|
+
// ❌ Inline literal colors
|
|
889
|
+
<div style={{ color: '#ffffff', background: '#1f2937' }}>
|
|
890
|
+
|
|
891
|
+
// ❌ Hardcoded dark-only colors
|
|
892
|
+
<div style={{ background: '#1e1e1e' }}> // Use rfp-bg-code-bg instead
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
**Theme-Aware Third-Party Libraries:**
|
|
896
|
+
|
|
897
|
+
For libraries with theme props (e.g., `react-syntax-highlighter`), use `useResolvedTheme()`:
|
|
898
|
+
|
|
899
|
+
```tsx
|
|
900
|
+
import { useResolvedTheme } from '@eternalheart/react-file-preview';
|
|
901
|
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
902
|
+
import { vscDarkPlus, vs } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
903
|
+
|
|
904
|
+
export const CodeRenderer = forwardRef<RendererHandle, Props>((props, ref) => {
|
|
905
|
+
const resolvedTheme = useResolvedTheme(); // 'dark' | 'light'
|
|
906
|
+
|
|
907
|
+
return (
|
|
908
|
+
<SyntaxHighlighter
|
|
909
|
+
language="javascript"
|
|
910
|
+
style={resolvedTheme === 'light' ? vs : vscDarkPlus}
|
|
911
|
+
>
|
|
912
|
+
{code}
|
|
913
|
+
</SyntaxHighlighter>
|
|
914
|
+
);
|
|
915
|
+
});
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
**Testing:**
|
|
919
|
+
|
|
920
|
+
Always test your custom renderer in both Light and Dark themes:
|
|
921
|
+
|
|
922
|
+
```tsx
|
|
923
|
+
<FilePreviewModal
|
|
924
|
+
files={files}
|
|
925
|
+
theme="light" // Switch between 'light', 'dark', 'auto'
|
|
926
|
+
customRenderers={[...]}
|
|
927
|
+
/>
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
Verify:
|
|
931
|
+
- Text is readable in both themes (no white-on-white or black-on-black)
|
|
932
|
+
- Borders and dividers are visible
|
|
933
|
+
- Hover states have sufficient contrast
|
|
934
|
+
- Code blocks follow theme (not always dark)
|
|
935
|
+
|
|
936
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f3a8.svg" width="20" height="20" alt="🎨" /> Custom Styling
|
|
534
937
|
|
|
535
938
|
The component is built with Tailwind CSS. You can customize styles by overriding CSS variables:
|
|
536
939
|
|
|
@@ -542,18 +945,18 @@ The component is built with Tailwind CSS. You can customize styles by overriding
|
|
|
542
945
|
}
|
|
543
946
|
```
|
|
544
947
|
|
|
545
|
-
## ⌨️ Keyboard Shortcuts
|
|
948
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/2328.svg" width="20" height="20" alt="⌨️" /> Keyboard Shortcuts
|
|
546
949
|
|
|
547
950
|
- `ESC` - Close preview
|
|
548
951
|
- `←` - Previous file
|
|
549
952
|
- `→` - Next file
|
|
550
953
|
- `Mouse Wheel` - Zoom image (image preview only)
|
|
551
954
|
|
|
552
|
-
## 📚 Documentation
|
|
955
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4da.svg" width="20" height="20" alt="📚" /> Documentation
|
|
553
956
|
|
|
554
957
|
- [Online Demo](https://wh131462.github.io/file-preview) - Live demo
|
|
555
958
|
|
|
556
|
-
## 🤖 Context7 Support
|
|
959
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f916.svg" width="20" height="20" alt="🤖" /> Context7 Support
|
|
557
960
|
|
|
558
961
|
This project supports [Context7](https://context7.com) MCP Server. If you are using AI coding assistants (such as Claude Code, Cursor, etc.), you can configure the Context7 MCP Server to get the latest documentation and code examples for `@eternalheart/react-file-preview`, enabling a better AI-assisted development experience.
|
|
559
962
|
|
|
@@ -565,33 +968,7 @@ This project supports [Context7](https://context7.com) MCP Server. If you are us
|
|
|
565
968
|
|
|
566
969
|
> For more details on configuring Context7, please visit [Context7 official documentation](https://github.com/upstash/context7).
|
|
567
970
|
|
|
568
|
-
##
|
|
569
|
-
|
|
570
|
-
### Bundle Size
|
|
571
|
-
|
|
572
|
-
- **ESM**: ~54 KB (gzipped: ~12 KB)
|
|
573
|
-
- **CJS**: ~37 KB (gzipped: ~11 KB)
|
|
574
|
-
- **CSS**: ~56 KB (gzipped: ~14 KB)
|
|
575
|
-
|
|
576
|
-
### Peer Dependencies
|
|
577
|
-
|
|
578
|
-
- `react`: ^18.0.0
|
|
579
|
-
- `react-dom`: ^18.0.0
|
|
580
|
-
|
|
581
|
-
### Exports
|
|
582
|
-
|
|
583
|
-
```json
|
|
584
|
-
{
|
|
585
|
-
".": {
|
|
586
|
-
"types": "./lib/index.d.ts",
|
|
587
|
-
"import": "./lib/index.mjs",
|
|
588
|
-
"require": "./lib/index.cjs"
|
|
589
|
-
},
|
|
590
|
-
"./style.css": "./lib/index.css"
|
|
591
|
-
}
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
## 🛠️ Development
|
|
971
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f6e0.svg" width="20" height="20" alt="🛠️" /> Development
|
|
595
972
|
|
|
596
973
|
### For Library Development
|
|
597
974
|
|
|
@@ -629,15 +1006,15 @@ react-file-preview/
|
|
|
629
1006
|
└── vite.config.lib.ts # Library build config
|
|
630
1007
|
```
|
|
631
1008
|
|
|
632
|
-
## 📄 License
|
|
1009
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f4c4.svg" width="20" height="20" alt="📄" /> License
|
|
633
1010
|
|
|
634
1011
|
[MIT](./LICENSE) © [EternalHeart](https://github.com/wh131462)
|
|
635
1012
|
|
|
636
|
-
## 🤝 Contributing
|
|
1013
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f91d.svg" width="20" height="20" alt="🤝" /> Contributing
|
|
637
1014
|
|
|
638
1015
|
Issues and Pull Requests are welcome!
|
|
639
1016
|
|
|
640
|
-
## 🔗 Links
|
|
1017
|
+
## <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/svg/1f517.svg" width="20" height="20" alt="🔗" /> Links
|
|
641
1018
|
|
|
642
1019
|
- [GitHub](https://github.com/wh131462/file-preview)
|
|
643
1020
|
- [npm](https://www.npmjs.com/package/@eternalheart/react-file-preview)
|