@eternalheart/react-file-preview 1.1.2 → 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 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":"AAgCA,OAAO,EAAe,gBAAgB,EAAY,cAAc,EAAE,MAAM,SAAS,CAAC;AAclF,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;AAgDD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+d5D,CAAC"}
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"}