@eternalheart/react-file-preview 1.1.1 → 1.1.3
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 +74 -0
- package/README.zh-CN.md +74 -0
- package/lib/FilePreviewContent.d.ts +13 -0
- package/lib/FilePreviewContent.d.ts.map +1 -0
- package/lib/FilePreviewEmbed.d.ts +16 -0
- package/lib/FilePreviewEmbed.d.ts.map +1 -0
- package/lib/FilePreviewModal.d.ts.map +1 -1
- package/lib/index.cjs +10 -10
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.mjs +2910 -2820
- package/lib/index.mjs.map +1 -1
- package/lib/renderers/ImageRenderer.d.ts +2 -0
- package/lib/renderers/ImageRenderer.d.ts.map +1 -1
- package/lib/renderers/VideoRenderer.d.ts.map +1 -1
- package/lib/utils/fileNormalizer.d.ts +4 -0
- package/lib/utils/fileNormalizer.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ A modern, feature-rich file preview component for React with support for images,
|
|
|
10
10
|
|
|
11
11
|
- 🎨 **Modern UI** - Apple-inspired minimalist design with glassmorphism effects
|
|
12
12
|
- 📁 **Multi-format Support** - Supports 20+ file formats
|
|
13
|
+
- 🪟 **Two Display Modes** - Full-screen modal **or** inline embedded preview
|
|
13
14
|
- 🖼️ **Powerful Image Viewer** - Zoom, rotate, drag, mouse wheel zoom
|
|
14
15
|
- 🎬 **Custom Video Player** - Built on Video.js, supports multiple video formats
|
|
15
16
|
- 🎵 **Custom Audio Player** - Beautiful audio control interface
|
|
@@ -188,6 +189,48 @@ function App() {
|
|
|
188
189
|
}
|
|
189
190
|
```
|
|
190
191
|
|
|
192
|
+
### Embedded Mode (`FilePreviewEmbed`)
|
|
193
|
+
|
|
194
|
+
Besides the full-screen modal, the library also ships an **embedded** variant that renders the preview inline inside any container. Useful for detail panels, side-by-side layouts, dashboards, etc.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { FilePreviewEmbed } from '@eternalheart/react-file-preview';
|
|
198
|
+
import '@eternalheart/react-file-preview/style.css';
|
|
199
|
+
import { useState } from 'react';
|
|
200
|
+
|
|
201
|
+
function InlinePreview() {
|
|
202
|
+
const [index, setIndex] = useState(0);
|
|
203
|
+
|
|
204
|
+
const files = [
|
|
205
|
+
'https://example.com/image.jpg',
|
|
206
|
+
{ name: 'document.pdf', type: 'application/pdf', url: '/doc.pdf' },
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
// The embedded preview fills its parent container by default.
|
|
211
|
+
<div style={{ width: '100%', height: 520 }}>
|
|
212
|
+
<FilePreviewEmbed
|
|
213
|
+
files={files}
|
|
214
|
+
currentIndex={index}
|
|
215
|
+
onNavigate={setIndex}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Differences from `FilePreviewModal`:
|
|
223
|
+
|
|
224
|
+
- No portal, no full-screen overlay, no `isOpen` / `onClose`
|
|
225
|
+
- Does **not** show the close button in the toolbar
|
|
226
|
+
- Keyboard navigation (←/→) is scoped to the embed container (focus-based)
|
|
227
|
+
- Size defaults to `width: 100%; height: 100%`; override via `width` / `height` props
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// Explicit size
|
|
231
|
+
<FilePreviewEmbed files={files} width={800} height={500} />
|
|
232
|
+
```
|
|
233
|
+
|
|
191
234
|
## 💡 Usage Examples
|
|
192
235
|
|
|
193
236
|
### Preview PowerPoint Files
|
|
@@ -277,6 +320,37 @@ const files = [
|
|
|
277
320
|
| `isOpen` | `boolean` | ✅ | Whether the modal is open |
|
|
278
321
|
| `onClose` | `() => void` | ✅ | Close callback |
|
|
279
322
|
| `onNavigate` | `(index: number) => void` | ❌ | Navigation callback |
|
|
323
|
+
| `customRenderers` | `CustomRenderer[]` | ❌ | Custom renderers for specific file types |
|
|
324
|
+
|
|
325
|
+
### FilePreviewEmbed Props
|
|
326
|
+
|
|
327
|
+
| Prop | Type | Required | Default | Description |
|
|
328
|
+
|------|------|----------|---------|-------------|
|
|
329
|
+
| `files` | `PreviewFileInput[]` | ✅ | - | Array of files |
|
|
330
|
+
| `currentIndex` | `number` | ❌ | `0` | Current file index |
|
|
331
|
+
| `onNavigate` | `(index: number) => void` | ❌ | - | Navigation callback |
|
|
332
|
+
| `customRenderers` | `CustomRenderer[]` | ❌ | - | Custom renderers |
|
|
333
|
+
| `width` | `number \| string` | ❌ | `'100%'` | Container width |
|
|
334
|
+
| `height` | `number \| string` | ❌ | `'100%'` | Container height |
|
|
335
|
+
| `className` | `string` | ❌ | - | Extra class on the root wrapper |
|
|
336
|
+
| `style` | `CSSProperties` | ❌ | - | Extra inline style on the root wrapper |
|
|
337
|
+
|
|
338
|
+
> `FilePreviewEmbed` has no `isOpen` / `onClose`. To hide/show it, conditionally render it from the parent. It also hides the close button in the toolbar.
|
|
339
|
+
|
|
340
|
+
### FilePreviewContent (advanced)
|
|
341
|
+
|
|
342
|
+
Both `FilePreviewModal` and `FilePreviewEmbed` are thin wrappers around the exported lower-level `FilePreviewContent` component. Use it directly when building a fully custom wrapper:
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
import { FilePreviewContent } from '@eternalheart/react-file-preview';
|
|
346
|
+
|
|
347
|
+
<FilePreviewContent
|
|
348
|
+
mode="embed" // or "modal"
|
|
349
|
+
files={files}
|
|
350
|
+
currentIndex={index}
|
|
351
|
+
onNavigate={setIndex}
|
|
352
|
+
/>
|
|
353
|
+
```
|
|
280
354
|
|
|
281
355
|
### File Type Definitions
|
|
282
356
|
|
package/README.zh-CN.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
- 🎨 **现代化 UI** - Apple 风格的简约设计,毛玻璃效果
|
|
10
10
|
- 📁 **多格式支持** - 支持 20+ 种文件格式
|
|
11
|
+
- 🪟 **两种展示模式** - 全屏弹窗 **或** 嵌入式内联预览
|
|
11
12
|
- 🖼️ **强大的图片查看器** - 缩放、旋转、拖拽、滚轮缩放
|
|
12
13
|
- 🎬 **自定义视频播放器** - 基于 Video.js,支持多种视频格式
|
|
13
14
|
- 🎵 **自定义音频播放器** - 精美的音频控制界面
|
|
@@ -186,6 +187,48 @@ function App() {
|
|
|
186
187
|
}
|
|
187
188
|
```
|
|
188
189
|
|
|
190
|
+
### 嵌入模式 (`FilePreviewEmbed`)
|
|
191
|
+
|
|
192
|
+
除了全屏弹窗,组件库还提供了**嵌入式**变体,可以将预览内联渲染到任意 div 容器中,适合详情面板、左右分栏布局、仪表盘等场景。
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { FilePreviewEmbed } from '@eternalheart/react-file-preview';
|
|
196
|
+
import '@eternalheart/react-file-preview/style.css';
|
|
197
|
+
import { useState } from 'react';
|
|
198
|
+
|
|
199
|
+
function InlinePreview() {
|
|
200
|
+
const [index, setIndex] = useState(0);
|
|
201
|
+
|
|
202
|
+
const files = [
|
|
203
|
+
'https://example.com/image.jpg',
|
|
204
|
+
{ name: 'document.pdf', type: 'application/pdf', url: '/doc.pdf' },
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
// 嵌入式预览默认填充父容器
|
|
209
|
+
<div style={{ width: '100%', height: 520 }}>
|
|
210
|
+
<FilePreviewEmbed
|
|
211
|
+
files={files}
|
|
212
|
+
currentIndex={index}
|
|
213
|
+
onNavigate={setIndex}
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
与 `FilePreviewModal` 的区别:
|
|
221
|
+
|
|
222
|
+
- 不使用 Portal、无全屏遮罩、没有 `isOpen` / `onClose`
|
|
223
|
+
- **不显示关闭按钮**
|
|
224
|
+
- 键盘导航 (←/→) 作用域限定在嵌入容器内 (基于 focus)
|
|
225
|
+
- 尺寸默认 `width: 100%; height: 100%`,可通过 `width` / `height` props 覆盖
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
// 显式指定尺寸
|
|
229
|
+
<FilePreviewEmbed files={files} width={800} height={500} />
|
|
230
|
+
```
|
|
231
|
+
|
|
189
232
|
## 💡 使用示例
|
|
190
233
|
|
|
191
234
|
### 预览 PowerPoint 文件
|
|
@@ -275,6 +318,37 @@ const files = [
|
|
|
275
318
|
| `isOpen` | `boolean` | ✅ | 是否打开预览 |
|
|
276
319
|
| `onClose` | `() => void` | ✅ | 关闭回调 |
|
|
277
320
|
| `onNavigate` | `(index: number) => void` | ❌ | 导航回调 |
|
|
321
|
+
| `customRenderers` | `CustomRenderer[]` | ❌ | 自定义渲染器 |
|
|
322
|
+
|
|
323
|
+
### FilePreviewEmbed Props
|
|
324
|
+
|
|
325
|
+
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
326
|
+
|------|------|------|--------|------|
|
|
327
|
+
| `files` | `PreviewFileInput[]` | ✅ | - | 文件列表 |
|
|
328
|
+
| `currentIndex` | `number` | ❌ | `0` | 当前文件索引 |
|
|
329
|
+
| `onNavigate` | `(index: number) => void` | ❌ | - | 导航回调 |
|
|
330
|
+
| `customRenderers` | `CustomRenderer[]` | ❌ | - | 自定义渲染器 |
|
|
331
|
+
| `width` | `number \| string` | ❌ | `'100%'` | 容器宽度 |
|
|
332
|
+
| `height` | `number \| string` | ❌ | `'100%'` | 容器高度 |
|
|
333
|
+
| `className` | `string` | ❌ | - | 根节点额外 className |
|
|
334
|
+
| `style` | `CSSProperties` | ❌ | - | 根节点额外内联样式 |
|
|
335
|
+
|
|
336
|
+
> `FilePreviewEmbed` 没有 `isOpen` / `onClose`,若要显示/隐藏,请在父组件中条件渲染。同时它不会显示工具栏上的关闭按钮。
|
|
337
|
+
|
|
338
|
+
### FilePreviewContent(高级用法)
|
|
339
|
+
|
|
340
|
+
`FilePreviewModal` 和 `FilePreviewEmbed` 都是基于底层 `FilePreviewContent` 组件的薄包装。当你需要构建完全自定义的容器时,可以直接使用它:
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
import { FilePreviewContent } from '@eternalheart/react-file-preview';
|
|
344
|
+
|
|
345
|
+
<FilePreviewContent
|
|
346
|
+
mode="embed" // 或 "modal"
|
|
347
|
+
files={files}
|
|
348
|
+
currentIndex={index}
|
|
349
|
+
onNavigate={setIndex}
|
|
350
|
+
/>
|
|
351
|
+
```
|
|
278
352
|
|
|
279
353
|
### 文件类型定义
|
|
280
354
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PreviewFileInput, CustomRenderer } from './types';
|
|
2
|
+
export interface FilePreviewContentProps {
|
|
3
|
+
files: PreviewFileInput[];
|
|
4
|
+
currentIndex: number;
|
|
5
|
+
onNavigate?: (index: number) => void;
|
|
6
|
+
customRenderers?: CustomRenderer[];
|
|
7
|
+
/** 运行模式:modal(弹窗) 或 embed(嵌入) */
|
|
8
|
+
mode?: 'modal' | 'embed';
|
|
9
|
+
/** 关闭回调,仅 modal 模式使用 */
|
|
10
|
+
onClose?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const FilePreviewContent: React.FC<FilePreviewContentProps>;
|
|
13
|
+
//# sourceMappingURL=FilePreviewContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAgCA,OAAO,EAAe,gBAAgB,EAAY,cAAc,EAAE,MAAM,SAAS,CAAC;AAclF,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AA+CD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAichE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PreviewFileInput, CustomRenderer } from './types';
|
|
2
|
+
interface FilePreviewEmbedProps {
|
|
3
|
+
files: PreviewFileInput[];
|
|
4
|
+
currentIndex?: number;
|
|
5
|
+
onNavigate?: (index: number) => void;
|
|
6
|
+
customRenderers?: CustomRenderer[];
|
|
7
|
+
/** 宽度,默认 100% 填充父容器 */
|
|
8
|
+
width?: number | string;
|
|
9
|
+
/** 高度,默认 100% 填充父容器 */
|
|
10
|
+
height?: number | string;
|
|
11
|
+
className?: string;
|
|
12
|
+
style?: React.CSSProperties;
|
|
13
|
+
}
|
|
14
|
+
export declare const FilePreviewEmbed: React.FC<FilePreviewEmbedProps>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=FilePreviewEmbed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePreviewEmbed.d.ts","sourceRoot":"","sources":["../src/FilePreviewEmbed.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA0B5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../src/FilePreviewModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../src/FilePreviewModal.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA8D5D,CAAC"}
|