@eternalheart/react-file-preview 1.0.0
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/LICENSE +22 -0
- package/README.md +384 -0
- package/README.zh-CN.md +383 -0
- package/lib/FilePreviewModal.d.ts +11 -0
- package/lib/FilePreviewModal.d.ts.map +1 -0
- package/lib/index.cjs +2 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.css +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.mjs +1478 -0
- package/lib/index.mjs.map +1 -0
- package/lib/renderers/AudioRenderer.d.ts +7 -0
- package/lib/renderers/AudioRenderer.d.ts.map +1 -0
- package/lib/renderers/DocxRenderer.d.ts +6 -0
- package/lib/renderers/DocxRenderer.d.ts.map +1 -0
- package/lib/renderers/ImageRenderer.d.ts +9 -0
- package/lib/renderers/ImageRenderer.d.ts.map +1 -0
- package/lib/renderers/MarkdownRenderer.d.ts +6 -0
- package/lib/renderers/MarkdownRenderer.d.ts.map +1 -0
- package/lib/renderers/PdfRenderer.d.ts +13 -0
- package/lib/renderers/PdfRenderer.d.ts.map +1 -0
- package/lib/renderers/PptxRenderer.d.ts +6 -0
- package/lib/renderers/PptxRenderer.d.ts.map +1 -0
- package/lib/renderers/TextRenderer.d.ts +7 -0
- package/lib/renderers/TextRenderer.d.ts.map +1 -0
- package/lib/renderers/UnsupportedRenderer.d.ts +8 -0
- package/lib/renderers/UnsupportedRenderer.d.ts.map +1 -0
- package/lib/renderers/VideoRenderer.d.ts +7 -0
- package/lib/renderers/VideoRenderer.d.ts.map +1 -0
- package/lib/renderers/XlsxRenderer.d.ts +6 -0
- package/lib/renderers/XlsxRenderer.d.ts.map +1 -0
- package/lib/types.d.ts +29 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils/fileNormalizer.d.ts +14 -0
- package/lib/utils/fileNormalizer.d.ts.map +1 -0
- package/lib/utils/pdfConfig.d.ts +3 -0
- package/lib/utils/pdfConfig.d.ts.map +1 -0
- package/package.json +113 -0
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# React File Preview [](https://www.npmjs.com/package/@eternalheart/react-file-preview)[](https://github.com/wh131462/react-file-preview/blob/master/LICENSE)[](https://www.npmjs.com/package/@eternalheart/react-file-preview)
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
一个现代化、功能丰富的 React 文件预览组件,支持图片、视频、音频、PDF、Office 文档(Word、Excel、PowerPoint)、Markdown 和代码文件预览。
|
|
6
|
+
|
|
7
|
+
## ✨ 特性
|
|
8
|
+
|
|
9
|
+
- 🎨 **现代化 UI** - Apple 风格的简约设计,毛玻璃效果
|
|
10
|
+
- 📁 **多格式支持** - 支持 20+ 种文件格式
|
|
11
|
+
- 🖼️ **强大的图片查看器** - 缩放、旋转、拖拽、滚轮缩放
|
|
12
|
+
- 🎬 **自定义视频播放器** - 基于 Video.js,支持多种视频格式
|
|
13
|
+
- 🎵 **自定义音频播放器** - 精美的音频控制界面
|
|
14
|
+
- 📄 **PDF 查看器** - 支持分页浏览
|
|
15
|
+
- 📊 **Office 文档支持** - Word、Excel、PowerPoint 文件预览
|
|
16
|
+
- 📝 **Markdown 渲染** - 支持 GitHub Flavored Markdown
|
|
17
|
+
- 💻 **代码高亮** - 支持 40+ 种编程语言
|
|
18
|
+
- 🎭 **流畅动画** - 基于 Framer Motion
|
|
19
|
+
- 📱 **响应式设计** - 适配各种屏幕尺寸
|
|
20
|
+
- ⌨️ **键盘导航** - 支持方向键和 ESC 键
|
|
21
|
+
- 🎯 **拖拽上传** - 支持拖拽文件上传
|
|
22
|
+
|
|
23
|
+
## 📦 安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 使用 npm
|
|
27
|
+
npm install react-file-preview
|
|
28
|
+
|
|
29
|
+
# 使用 yarn
|
|
30
|
+
yarn add react-file-preview
|
|
31
|
+
|
|
32
|
+
# 使用 pnpm
|
|
33
|
+
pnpm add react-file-preview
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**重要提示:** 你还需要导入 CSS 文件:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import 'react-file-preview/style.css';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🚀 快速开始
|
|
43
|
+
|
|
44
|
+
📖 **第一次使用?** 查看 [快速开始指南](./QUICK_START.md) 获取 5 分钟入门教程!
|
|
45
|
+
|
|
46
|
+
### 基础用法
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { FilePreviewModal } from 'react-file-preview';
|
|
50
|
+
import 'react-file-preview/style.css';
|
|
51
|
+
import { useState } from 'react';
|
|
52
|
+
|
|
53
|
+
function App() {
|
|
54
|
+
const [files, setFiles] = useState([]);
|
|
55
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
56
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
57
|
+
|
|
58
|
+
const handleFileSelect = (file: File) => {
|
|
59
|
+
// 方法 1: 直接传入 File 对象(推荐)
|
|
60
|
+
setFiles([file]);
|
|
61
|
+
setCurrentIndex(0);
|
|
62
|
+
setIsOpen(true);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<input
|
|
68
|
+
type="file"
|
|
69
|
+
onChange={(e) => e.target.files?.[0] && handleFileSelect(e.target.files[0])}
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<FilePreviewModal
|
|
73
|
+
files={files}
|
|
74
|
+
currentIndex={currentIndex}
|
|
75
|
+
isOpen={isOpen}
|
|
76
|
+
onClose={() => setIsOpen(false)}
|
|
77
|
+
onNavigate={setCurrentIndex}
|
|
78
|
+
/>
|
|
79
|
+
</>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 多种输入类型
|
|
85
|
+
|
|
86
|
+
组件支持三种类型的文件输入:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { FilePreviewModal, PreviewFileInput } from '@eternalheart/react-file-preview';
|
|
90
|
+
import '@eternalheart/react-file-preview/style.css';
|
|
91
|
+
|
|
92
|
+
function App() {
|
|
93
|
+
const files: PreviewFileInput[] = [
|
|
94
|
+
// 1. 原生 File 对象
|
|
95
|
+
file1,
|
|
96
|
+
|
|
97
|
+
// 2. HTTP URL 字符串
|
|
98
|
+
'https://example.com/image.jpg',
|
|
99
|
+
|
|
100
|
+
// 3. 带元数据的文件对象
|
|
101
|
+
{
|
|
102
|
+
name: 'document.pdf',
|
|
103
|
+
type: 'application/pdf',
|
|
104
|
+
url: '/path/to/document.pdf',
|
|
105
|
+
size: 1024,
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<FilePreviewModal
|
|
111
|
+
files={files}
|
|
112
|
+
currentIndex={0}
|
|
113
|
+
isOpen={true}
|
|
114
|
+
onClose={() => {}}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 💡 使用示例
|
|
121
|
+
|
|
122
|
+
### 预览 PowerPoint 文件
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { FilePreviewModal } from '@eternalheart/react-file-preview';
|
|
126
|
+
import { useState } from 'react';
|
|
127
|
+
|
|
128
|
+
function PptPreview() {
|
|
129
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
130
|
+
|
|
131
|
+
const pptFile = {
|
|
132
|
+
name: 'presentation.pptx',
|
|
133
|
+
type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
134
|
+
url: '/path/to/your/presentation.pptx',
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<>
|
|
139
|
+
<button onClick={() => setIsOpen(true)}>
|
|
140
|
+
预览 PPT
|
|
141
|
+
</button>
|
|
142
|
+
|
|
143
|
+
<FilePreviewModal
|
|
144
|
+
files={[pptFile]}
|
|
145
|
+
currentIndex={0}
|
|
146
|
+
isOpen={isOpen}
|
|
147
|
+
onClose={() => setIsOpen(false)}
|
|
148
|
+
/>
|
|
149
|
+
</>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 预览多个文件
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
const files = [
|
|
158
|
+
{ name: 'image.jpg', type: 'image/jpeg', url: '/path/to/image.jpg' },
|
|
159
|
+
{ name: 'document.pdf', type: 'application/pdf', url: '/path/to/document.pdf' },
|
|
160
|
+
{ name: 'presentation.pptx', type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', url: '/path/to/presentation.pptx' },
|
|
161
|
+
{ name: 'spreadsheet.xlsx', type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', url: '/path/to/spreadsheet.xlsx' },
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
<FilePreviewModal
|
|
165
|
+
files={files}
|
|
166
|
+
currentIndex={0}
|
|
167
|
+
isOpen={isOpen}
|
|
168
|
+
onClose={() => setIsOpen(false)}
|
|
169
|
+
onNavigate={setCurrentIndex}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 📖 支持的文件格式
|
|
174
|
+
|
|
175
|
+
### 图片
|
|
176
|
+
- **格式**: JPG, PNG, GIF, WebP, SVG, BMP, ICO
|
|
177
|
+
- **功能**: 缩放 (0.5x - 5x)、旋转、拖拽、滚轮缩放、双击重置
|
|
178
|
+
|
|
179
|
+
### 视频
|
|
180
|
+
- **格式**: MP4, WebM, OGG, MOV, AVI, MKV, M4V, 3GP, FLV
|
|
181
|
+
- **功能**: 自定义播放器、进度控制、音量调节、全屏播放
|
|
182
|
+
|
|
183
|
+
### 音频
|
|
184
|
+
- **格式**: MP3, WAV, OGG, M4A, AAC, FLAC
|
|
185
|
+
- **功能**: 自定义播放器、进度条、音量控制、快进/快退
|
|
186
|
+
|
|
187
|
+
### 文档
|
|
188
|
+
- **PDF**: 分页浏览、缩放
|
|
189
|
+
- **Word**: DOCX 格式支持
|
|
190
|
+
- **Excel**: XLSX 格式支持
|
|
191
|
+
- **PowerPoint**: PPTX/PPT 格式支持、幻灯片预览
|
|
192
|
+
|
|
193
|
+
### 代码 & 文本
|
|
194
|
+
- **Markdown**: GitHub Flavored Markdown,代码高亮
|
|
195
|
+
- **代码文件**: JS, TS, Python, Java, C++, Go, Rust 等 40+ 种语言
|
|
196
|
+
- **文本文件**: TXT, LOG, CSV, JSON, YAML, XML 等
|
|
197
|
+
|
|
198
|
+
## 🎮 API 参考
|
|
199
|
+
|
|
200
|
+
### FilePreviewModal Props
|
|
201
|
+
|
|
202
|
+
| 属性 | 类型 | 必填 | 说明 |
|
|
203
|
+
|------|------|------|------|
|
|
204
|
+
| `files` | `PreviewFileInput[]` | ✅ | 文件列表(支持 File 对象、文件对象或 URL 字符串) |
|
|
205
|
+
| `currentIndex` | `number` | ✅ | 当前文件索引 |
|
|
206
|
+
| `isOpen` | `boolean` | ✅ | 是否打开预览 |
|
|
207
|
+
| `onClose` | `() => void` | ✅ | 关闭回调 |
|
|
208
|
+
| `onNavigate` | `(index: number) => void` | ❌ | 导航回调 |
|
|
209
|
+
|
|
210
|
+
### 文件类型定义
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// 支持三种文件输入类型
|
|
214
|
+
type PreviewFileInput = File | PreviewFileLink | string;
|
|
215
|
+
|
|
216
|
+
// 1. 原生 File 对象(浏览器 File API)
|
|
217
|
+
const file: File = ...;
|
|
218
|
+
|
|
219
|
+
// 2. 文件对象
|
|
220
|
+
interface PreviewFileLink {
|
|
221
|
+
id?: string; // 可选的唯一标识符
|
|
222
|
+
name: string; // 文件名
|
|
223
|
+
type: string; // MIME 类型
|
|
224
|
+
url: string; // 文件 URL (支持 blob URL 和 HTTP URL)
|
|
225
|
+
size?: number; // 文件大小(字节)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 3. HTTP URL 字符串
|
|
229
|
+
const url: string = 'https://example.com/file.pdf';
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 使用示例
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// 方式 1: 使用原生 File 对象
|
|
236
|
+
const files = [file1, file2]; // File 对象数组
|
|
237
|
+
|
|
238
|
+
// 方式 2: 使用 HTTP URL 字符串
|
|
239
|
+
const files = [
|
|
240
|
+
'https://example.com/image.jpg',
|
|
241
|
+
'https://example.com/document.pdf',
|
|
242
|
+
];
|
|
243
|
+
|
|
244
|
+
// 方式 3: 使用文件对象
|
|
245
|
+
const files = [
|
|
246
|
+
{
|
|
247
|
+
name: 'presentation.pptx',
|
|
248
|
+
type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
249
|
+
url: '/path/to/presentation.pptx',
|
|
250
|
+
},
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
// 方式 4: 混合使用
|
|
254
|
+
const files = [
|
|
255
|
+
file1, // File 对象
|
|
256
|
+
'https://example.com/image.jpg', // URL 字符串
|
|
257
|
+
{ name: 'doc.pdf', type: 'application/pdf', url: '/doc.pdf' }, // 文件对象
|
|
258
|
+
];
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 支持的 MIME 类型
|
|
262
|
+
|
|
263
|
+
#### Office 文档
|
|
264
|
+
- **Word**: `application/vnd.openxmlformats-officedocument.wordprocessingml.document` (.docx)
|
|
265
|
+
- **Excel**: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` (.xlsx)
|
|
266
|
+
- **PowerPoint**: `application/vnd.openxmlformats-officedocument.presentationml.presentation` (.pptx)
|
|
267
|
+
- **PowerPoint (旧版)**: `application/vnd.ms-powerpoint` (.ppt)
|
|
268
|
+
|
|
269
|
+
#### 其他文档
|
|
270
|
+
- **PDF**: `application/pdf`
|
|
271
|
+
|
|
272
|
+
#### 媒体文件
|
|
273
|
+
- **图片**: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml`, 等
|
|
274
|
+
- **视频**: `video/mp4`, `video/webm`, `video/ogg`, 等
|
|
275
|
+
- **音频**: `audio/mpeg`, `audio/wav`, `audio/ogg`, 等
|
|
276
|
+
|
|
277
|
+
#### 文本文件
|
|
278
|
+
- **Markdown**: 文件扩展名 `.md` 或 `.markdown`
|
|
279
|
+
- **代码**: 根据文件扩展名自动识别 (`.js`, `.ts`, `.py`, `.java`, 等)
|
|
280
|
+
- **纯文本**: `text/plain`, `text/csv`, 等
|
|
281
|
+
|
|
282
|
+
## 🎨 自定义样式
|
|
283
|
+
|
|
284
|
+
组件使用 Tailwind CSS 构建,您可以通过覆盖 CSS 变量来自定义样式:
|
|
285
|
+
|
|
286
|
+
```css
|
|
287
|
+
/* 自定义主题色 */
|
|
288
|
+
:root {
|
|
289
|
+
--primary-color: #8b5cf6;
|
|
290
|
+
--secondary-color: #ec4899;
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## ⌨️ 键盘快捷键
|
|
295
|
+
|
|
296
|
+
- `ESC` - 关闭预览
|
|
297
|
+
- `←` - 上一个文件
|
|
298
|
+
- `→` - 下一个文件
|
|
299
|
+
- `滚轮` - 缩放图片 (仅图片预览)
|
|
300
|
+
|
|
301
|
+
## 📚 文档
|
|
302
|
+
|
|
303
|
+
- [在线演示](https://wh131462.github.io/react-file-preview) - 在线 Demo
|
|
304
|
+
|
|
305
|
+
## 📦 包信息
|
|
306
|
+
|
|
307
|
+
### 打包体积
|
|
308
|
+
|
|
309
|
+
- **ESM**: ~54 KB (gzipped: ~12 KB)
|
|
310
|
+
- **CJS**: ~37 KB (gzipped: ~11 KB)
|
|
311
|
+
- **CSS**: ~56 KB (gzipped: ~14 KB)
|
|
312
|
+
|
|
313
|
+
### Peer Dependencies
|
|
314
|
+
|
|
315
|
+
- `react`: ^18.0.0
|
|
316
|
+
- `react-dom`: ^18.0.0
|
|
317
|
+
|
|
318
|
+
### 导出
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
".": {
|
|
323
|
+
"types": "./lib/index.d.ts",
|
|
324
|
+
"import": "./lib/index.mjs",
|
|
325
|
+
"require": "./lib/index.cjs"
|
|
326
|
+
},
|
|
327
|
+
"./style.css": "./lib/index.css"
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## 🛠️ 开发
|
|
332
|
+
|
|
333
|
+
### 库开发
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# 克隆仓库
|
|
337
|
+
git clone https://github.com/wh131462/react-file-preview.git
|
|
338
|
+
|
|
339
|
+
# 安装依赖
|
|
340
|
+
pnpm install
|
|
341
|
+
|
|
342
|
+
# 启动开发服务器(演示应用)
|
|
343
|
+
pnpm dev
|
|
344
|
+
|
|
345
|
+
# 构建库(用于 npm 发布)
|
|
346
|
+
pnpm build:lib
|
|
347
|
+
|
|
348
|
+
# 构建演示应用(用于 GitHub Pages)
|
|
349
|
+
pnpm build:demo
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 项目结构
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
react-file-preview/
|
|
356
|
+
├── src/
|
|
357
|
+
│ ├── index.ts # 库入口文件
|
|
358
|
+
│ ├── FilePreviewModal.tsx # 主组件
|
|
359
|
+
│ ├── types.ts # 类型定义
|
|
360
|
+
│ ├── utils/ # 工具函数
|
|
361
|
+
│ ├── renderers/ # 文件类型渲染器
|
|
362
|
+
│ ├── App.tsx # 演示应用
|
|
363
|
+
│ └── main.tsx # 演示应用入口
|
|
364
|
+
├── lib/ # 构建后的库(npm 包)
|
|
365
|
+
├── dist/ # 构建后的演示应用(GitHub Pages)
|
|
366
|
+
└── vite.config.lib.ts # 库构建配置
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## 📄 许可证
|
|
370
|
+
|
|
371
|
+
[MIT](./LICENSE) © [EternalHeart](https://github.com/wh131462)
|
|
372
|
+
|
|
373
|
+
## 🤝 贡献
|
|
374
|
+
|
|
375
|
+
欢迎提交 Issue 和 Pull Request!
|
|
376
|
+
|
|
377
|
+
## 🔗 相关链接
|
|
378
|
+
|
|
379
|
+
- [GitHub](https://github.com/wh131462/react-file-preview)
|
|
380
|
+
- [npm](https://www.npmjs.com/package/@eternalheart/react-file-preview)
|
|
381
|
+
- [在线演示](https://wh131462.github.io/react-file-preview)
|
|
382
|
+
- [问题反馈](https://github.com/wh131462/react-file-preview/issues)
|
|
383
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PreviewFileInput } from './types';
|
|
2
|
+
interface FilePreviewModalProps {
|
|
3
|
+
files: PreviewFileInput[];
|
|
4
|
+
currentIndex: number;
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
onNavigate?: (index: number) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const FilePreviewModal: React.FC<FilePreviewModalProps>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=FilePreviewModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../src/FilePreviewModal.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAe,gBAAgB,EAAY,MAAM,SAAS,CAAC;AAalE,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;CACtC;AA6CD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA2S5D,CAAC"}
|
package/lib/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),D=require("framer-motion"),y=require("lucide-react"),P=require("react-pdf"),X=require("mammoth"),U=require("xlsx"),W=require("pptx-preview"),V=require("video.js"),_=require("react-markdown"),Z=require("remark-gfm"),O=require("react-syntax-highlighter");function G(s){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const o in s)if(o!=="default"){const c=Object.getOwnPropertyDescriptor(s,o);Object.defineProperty(r,o,c.get?c:{enumerable:!0,get:()=>s[o]})}}return r.default=s,Object.freeze(r)}const $=G(U);function I(s){try{const c=new URL(s).pathname.split("/").pop()||"file";return decodeURIComponent(c)}catch{const r=s.split("/").pop()||"file";return decodeURIComponent(r)}}function z(s){var c;const r=((c=s.split(".").pop())==null?void 0:c.toLowerCase())||"";return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",bmp:"image/bmp",ico:"image/x-icon",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",ogv:"video/ogg",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",m4v:"video/x-m4v","3gp":"video/3gpp",flv:"video/x-flv",mp3:"audio/mpeg",wav:"audio/wav",m4a:"audio/mp4",aac:"audio/aac",flac:"audio/flac",pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",ppt:"application/vnd.ms-powerpoint",txt:"text/plain",md:"text/markdown",markdown:"text/markdown",json:"application/json",xml:"application/xml",html:"text/html",css:"text/css",js:"text/javascript",ts:"text/typescript",jsx:"text/javascript",tsx:"text/typescript",py:"text/x-python",java:"text/x-java",cpp:"text/x-c++src",c:"text/x-csrc",cs:"text/x-csharp",php:"text/x-php",rb:"text/x-ruby",go:"text/x-go",rs:"text/x-rust",yaml:"text/yaml",yml:"text/yaml"}[r]||"application/octet-stream"}function H(s,r=0){if(s instanceof File)return{id:`file-${Date.now()}-${r}`,name:s.name,url:URL.createObjectURL(s),type:s.type||z(s.name),size:s.size};if(typeof s=="string"){const o=I(s);return{id:`url-${Date.now()}-${r}`,name:o,url:s,type:z(o)}}return{id:s.id||`link-${Date.now()}-${r}`,name:s.name,url:s.url,type:s.type||z(s.name),size:s.size}}function B(s){return s.map((r,o)=>H(r,o))}const Y=({url:s,zoom:r,rotation:o,onZoomChange:c})=>{const[d,u]=t.useState(!1),[i,n]=t.useState(null),[a,w]=t.useState({x:0,y:0}),[x,h]=t.useState(!1),[b,l]=t.useState({x:0,y:0}),[m,f]=t.useState(1),j=t.useRef(null);t.useEffect(()=>{u(!1),n(null),w({x:0,y:0}),f(1)},[s]),t.useEffect(()=>{f(r)},[r]),t.useEffect(()=>{w({x:0,y:0})},[r,o]);const N=()=>{u(!0)},S=()=>{n("图片加载失败"),u(!0)},C=()=>{w({x:0,y:0})},R=t.useCallback(v=>{v.preventDefault(),v.stopPropagation();const E=v.deltaY>0?-.1:.1;f(g=>{const T=Math.max(.5,Math.min(5,g+E));return c&&c(T),T})},[c]),L=t.useCallback(v=>{v.button===0&&(h(!0),l({x:v.clientX-a.x,y:v.clientY-a.y}))},[a]),p=t.useCallback(v=>{x&&w({x:v.clientX-b.x,y:v.clientY-b.y})},[x,b]),k=t.useCallback(()=>{h(!1)},[]);return e.jsxs("div",{ref:j,className:"flex items-center justify-center w-full h-full overflow-hidden",onWheel:R,onMouseDown:L,onMouseMove:p,onMouseUp:k,onMouseLeave:k,style:{cursor:x?"grabbing":"grab"},children:[!d&&!i&&e.jsx("div",{className:"flex items-center justify-center",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})}),i&&e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:i})}),e.jsx(D.motion.img,{src:s,alt:"Preview",className:`max-w-none select-none ${d?"":"hidden"}`,style:{transform:`translate(${a.x}px, ${a.y}px) scale(${m}) rotate(${o}deg)`,transformOrigin:"center",transition:x?"none":"transform 0.3s ease-out"},onLoad:N,onError:S,onDoubleClick:C,initial:{opacity:0},animate:{opacity:d?1:0},transition:{duration:.3},draggable:!1})]})},K=P.pdfjs.version,Q="/pdf.worker.min.mjs";P.pdfjs.GlobalWorkerOptions.workerSrc=Q;const J=P.pdfjs.GlobalWorkerOptions.workerSrc,q=`https://unpkg.com/pdfjs-dist@${K}/build/pdf.worker.min.mjs`;typeof window<"u"&&window.addEventListener("error",s=>{var r;(r=s.message)!=null&&r.includes("pdf.worker")&&P.pdfjs.GlobalWorkerOptions.workerSrc===J&&(console.warn("本地 PDF worker 加载失败,切换到 CDN:",q),P.pdfjs.GlobalWorkerOptions.workerSrc=q)});const ee=({url:s,zoom:r,currentPage:o,onPageChange:c,onTotalPagesChange:d})=>{const[u,i]=t.useState(0),[n,a]=t.useState(null),w=t.useRef(null),x=t.useRef(new Map);t.useEffect(()=>{a(null)},[s]);const h=({numPages:f})=>{i(f),d(f),c(1)},b=f=>{console.error("PDF 加载错误:",f),a("PDF 文件加载失败")},l=t.useCallback(()=>{if(!w.current)return;const f=w.current,j=f.scrollTop,N=f.clientHeight,S=j+N/2;let C=1,R=1/0;x.current.forEach((L,p)=>{const k=L.getBoundingClientRect(),v=f.getBoundingClientRect(),E=k.top-v.top+k.height/2+j,g=Math.abs(E-S);g<R&&(R=g,C=p)}),C!==o&&c(C)},[o,c]);t.useEffect(()=>{const f=w.current;if(f)return f.addEventListener("scroll",l),()=>f.removeEventListener("scroll",l)},[l]);const m=t.useCallback((f,j)=>{j?x.current.set(f,j):x.current.delete(f)},[]);return e.jsxs("div",{ref:w,className:"flex flex-col items-center w-full h-full overflow-auto py-8 px-4",children:[n&&e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:n})}),!n&&e.jsx(P.Document,{file:s,onLoadSuccess:h,onLoadError:b,loading:e.jsx("div",{className:"flex items-center justify-center min-h-screen",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})}),children:e.jsx("div",{className:"flex flex-col gap-4",children:Array.from(new Array(u),(f,j)=>{const N=j+1;return e.jsxs("div",{ref:S=>m(N,S),className:"relative",children:[e.jsx(P.Page,{pageNumber:N,scale:r,loading:e.jsx("div",{className:"flex items-center justify-center p-8 bg-white/5 rounded-lg min-h-[600px]",children:e.jsx("div",{className:"w-8 h-8 border-4 border-white/20 border-t-white rounded-full animate-spin"})}),renderTextLayer:!0,renderAnnotationLayer:!0,className:"shadow-2xl"}),e.jsx("div",{className:"absolute top-2 right-2 bg-black/60 backdrop-blur-sm text-white text-xs px-3 py-1 rounded-full",children:N})]},`page_${N}`)})})}),u>0&&e.jsxs("div",{className:"sticky bottom-4 mt-8 bg-black/60 backdrop-blur-xl text-white px-6 py-3 rounded-full text-sm font-medium shadow-2xl border border-white/10",children:["第 ",o," 页 / 共 ",u," 页"]})]})},te=({url:s})=>{const[r,o]=t.useState(""),[c,d]=t.useState(!0),[u,i]=t.useState(null);return t.useEffect(()=>{(async()=>{d(!0),i(null),o("");try{const a=await fetch(s);if(!a.ok)throw new Error("文件加载失败");const w=await a.arrayBuffer(),x=await X.convertToHtml({arrayBuffer:w});o(x.value)}catch(a){console.error("Docx 解析错误:",a),i("Word 文档解析失败")}finally{d(!1)}})()},[s]),c?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})}):u?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:u})})}):e.jsx("div",{className:"w-full h-full overflow-auto p-8",children:e.jsx("div",{className:"max-w-4xl mx-auto bg-white rounded-lg shadow-2xl p-12",dangerouslySetInnerHTML:{__html:r},style:{fontFamily:"system-ui, -apple-system, sans-serif",lineHeight:"1.6",color:"#333"}})})},se=({url:s})=>{const[r,o]=t.useState([]),[c,d]=t.useState(0),[u,i]=t.useState(!0),[n,a]=t.useState(null);if(t.useEffect(()=>{(async()=>{i(!0),a(null),o([]);try{const h=await fetch(s);if(!h.ok)throw new Error("文件加载失败");const b=await h.arrayBuffer(),l=$.read(b,{type:"array"}),m=l.SheetNames.map(f=>{const j=l.Sheets[f],N=$.utils.sheet_to_json(j,{header:1});return{name:f,data:N}});o(m),d(0)}catch(h){console.error("Excel 解析错误:",h),a("Excel 文件解析失败")}finally{i(!1)}})()},[s]),u)return e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})});if(n)return e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:n})})});const w=r[c];return e.jsxs("div",{className:"w-full h-full flex flex-col overflow-hidden",children:[r.length>1&&e.jsx("div",{className:"flex gap-2 p-4 bg-black/20 backdrop-blur-sm overflow-x-auto border-b border-white/10",children:r.map((x,h)=>e.jsx("button",{onClick:()=>d(h),className:`px-4 py-2 rounded-lg text-sm font-medium transition-all ${c===h?"bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-lg":"bg-white/10 text-white hover:bg-white/20"}`,children:x.name},h))}),e.jsx("div",{className:"flex-1 overflow-auto p-8",children:e.jsx("div",{className:"inline-block min-w-full bg-gradient-to-br from-gray-800/90 to-gray-900/90 backdrop-blur-xl rounded-2xl shadow-2xl overflow-hidden border border-white/10",children:e.jsx("table",{className:"min-w-full divide-y divide-white/10",children:e.jsx("tbody",{className:"divide-y divide-white/10",children:w==null?void 0:w.data.map((x,h)=>e.jsx("tr",{className:`transition-colors ${h===0?"bg-gradient-to-r from-purple-500/20 to-pink-500/20 font-semibold":"hover:bg-white/5"}`,children:x.map((b,l)=>e.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-200 border-r border-white/10",children:String(b??"")},l))},h))})})})})]})},re=({url:s})=>{const[r,o]=t.useState(!0),[c,d]=t.useState(null),u=t.useRef(null),i=t.useRef(null),n=t.useRef(null),a=t.useRef(null),w=t.useRef(null),x=t.useRef({width:0,height:0}),h=t.useCallback(()=>{if(!u.current)return{width:960,height:540};const l=u.current.clientWidth,m=Math.floor(l*9/16);return console.log("计算尺寸:",{width:l,height:m}),{width:l,height:m}},[]),b=t.useCallback(async()=>{if(!(!u.current||!a.current)){console.log("重新初始化预览器...");try{if(i.current)try{i.current.destroy()}catch(f){console.error("销毁预览器失败:",f)}u.current.innerHTML="";const l=h();console.log("重新初始化使用尺寸:",l);const m=W.init(u.current,{width:l.width,height:l.height});i.current=m,await m.preview(a.current),console.log("重新初始化成功")}catch(l){console.error("重新初始化失败:",l)}}},[h]);return t.useEffect(()=>{if(!u.current)return;let l=!0;const m=()=>{if(l){l=!1;const C=h();x.current=C;return}const f=h(),j=x.current,N=Math.abs(j.width-f.width),S=Math.abs(j.height-f.height);if(N<10&&S<10){console.log("尺寸变化太小,忽略");return}console.log("检测到尺寸变化:",{old:j,new:f,diff:{width:N,height:S}}),x.current=f,w.current&&clearTimeout(w.current),w.current=window.setTimeout(()=>{i.current&&a.current&&(console.log("尺寸变化,准备重新初始化"),b())},800)};return n.current=new ResizeObserver(()=>{m()}),n.current.observe(u.current),()=>{n.current&&n.current.disconnect(),w.current&&clearTimeout(w.current)}},[h,b]),t.useEffect(()=>{let l=!0;const m=async()=>{if(!u.current){console.log("Container ref not ready");return}o(!0),d(null);try{console.log("开始加载 PPTX:",s);const j=await fetch(s);if(!j.ok)throw new Error("文件加载失败");const N=await j.arrayBuffer();if(a.current=N,console.log("文件加载成功,大小:",N.byteLength),!l)return;u.current&&(u.current.innerHTML="");const S=h();console.log("使用尺寸:",S),console.log("初始化预览器...");const C=W.init(u.current,{width:S.width,height:S.height});i.current=C,console.log("开始预览..."),C.preview(N).then(()=>{console.log("预览成功"),l&&o(!1)}).catch(R=>{console.error("预览失败:",R),l&&(d("PPT 文件预览失败"),o(!1))})}catch(j){console.error("PPTX 解析错误:",j),l&&(d(j instanceof Error?j.message:"PPT 文件解析失败"),o(!1))}},f=setTimeout(()=>{m()},100);return()=>{if(l=!1,clearTimeout(f),a.current=null,i.current)try{i.current.destroy()}catch(j){console.error("销毁预览器失败:",j)}i.current=null}},[s,h]),e.jsxs("div",{className:"relative flex flex-col items-center w-full h-full pt-[8px]",children:[r&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-3 border-4 border-white/20 border-t-white rounded-full animate-spin"}),e.jsx("p",{className:"text-sm text-white/70 font-medium",children:"加载 PPT 中..."})]})}),c&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl",children:e.jsxs("div",{className:"text-center max-w-md",children:[e.jsx("div",{className:"w-32 h-32 mx-auto mb-6 rounded-3xl bg-gradient-to-br from-orange-500 via-red-500 to-pink-500 flex items-center justify-center shadow-2xl",children:e.jsx(y.Presentation,{className:"w-16 h-16 text-white"})}),e.jsx("p",{className:"text-xl text-white/90 mb-3 font-medium",children:"PPT 预览"}),e.jsx("p",{className:"text-sm text-white/60 mb-6",children:c||"浏览器暂不支持直接预览 PPT 文件"}),e.jsxs("a",{href:s,download:!0,className:"inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-purple-500 to-pink-500 text-white rounded-xl hover:scale-105 transition-all shadow-lg",children:[e.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"})}),"下载文件"]}),e.jsx("p",{className:"text-xs text-white/40 mt-4",children:"提示:可以使用 Microsoft PowerPoint 或 WPS 打开"})]})}),e.jsx("div",{ref:u,className:"pptx-wrapper w-full max-w-6xl"})]})},oe=s=>{var c;const r=((c=s.split(".").pop())==null?void 0:c.toLowerCase().split("?")[0])||"";return{mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",ogv:"video/ogg",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",m4v:"video/mp4","3gp":"video/3gpp",flv:"video/x-flv"}[r]||"video/mp4"},ne=({url:s})=>{const[r,o]=t.useState(null),[c,d]=t.useState(!0),u=t.useRef(null),i=t.useRef(null);return t.useEffect(()=>{if(!i.current&&u.current){const n=document.createElement("video-js");n.classList.add("vjs-big-play-centered","vjs-theme-apple"),u.current.appendChild(n);const a=oe(s),x=V(n,{controls:!0,responsive:!0,fluid:!0,preload:"auto",controlBar:{children:["playToggle","volumePanel","currentTimeDisplay","timeDivider","durationDisplay","progressControl","remainingTimeDisplay","fullscreenToggle"],volumePanel:{inline:!1}},html5:{vhs:{overrideNative:!0},nativeVideoTracks:!1,nativeAudioTracks:!1,nativeTextTracks:!1},sources:a==="video/quicktime"?[{src:s,type:"video/quicktime"},{src:s,type:"video/mp4"}]:[{src:s,type:a}]});x.on("loadeddata",()=>{d(!1)}),x.on("error",()=>{const h=x.error();console.error("Video.js error:",h),o(`视频加载失败: ${(h==null?void 0:h.message)||"未知错误"}`),d(!1)}),i.current=x}},[s]),t.useEffect(()=>{const n=i.current;return()=>{n&&!n.isDisposed()&&(n.dispose(),i.current=null)}},[]),r?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-16 h-16 mx-auto mb-4 rounded-full bg-red-500/10 flex items-center justify-center",children:e.jsx("svg",{className:"w-8 h-8 text-red-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})}),e.jsx("p",{className:"text-lg font-medium text-white/90 mb-2",children:"视频加载失败"}),e.jsx("p",{className:"text-sm text-white/60",children:r})]})}):e.jsx("div",{className:"flex items-center justify-center w-full h-full p-8",children:e.jsxs("div",{className:"w-full max-w-5xl relative",children:[c&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded-2xl z-10",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-12 h-12 mx-auto mb-3 border-3 border-white/20 border-t-white rounded-full animate-spin"}),e.jsx("p",{className:"text-sm text-white/70 font-medium",children:"加载视频中..."})]})}),e.jsx("div",{ref:u,className:"overflow-hidden",style:{boxShadow:"0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)"}})]})})},le=({url:s,fileName:r})=>{const[o,c]=t.useState(null),[d,u]=t.useState(!1),[i,n]=t.useState(0),[a,w]=t.useState(0),[x,h]=t.useState(1),[b,l]=t.useState(!1),m=t.useRef(null);t.useEffect(()=>{const p=m.current;if(!p)return;const k=()=>{isNaN(p.currentTime)||n(p.currentTime)},v=()=>{!isNaN(p.duration)&&isFinite(p.duration)&&w(p.duration)},E=()=>u(!1),g=()=>v();return p.addEventListener("timeupdate",k),p.addEventListener("loadedmetadata",v),p.addEventListener("durationchange",v),p.addEventListener("canplay",g),p.addEventListener("ended",E),p.readyState>=1&&v(),()=>{p.removeEventListener("timeupdate",k),p.removeEventListener("loadedmetadata",v),p.removeEventListener("durationchange",v),p.removeEventListener("canplay",g),p.removeEventListener("ended",E)}},[]);const f=()=>{m.current&&(d?m.current.pause():m.current.play(),u(!d))},j=p=>{const k=parseFloat(p.target.value);n(k),m.current&&(m.current.currentTime=k)},N=p=>{const k=parseFloat(p.target.value);h(k),m.current&&(m.current.volume=k),k>0&&l(!1)},S=()=>{m.current&&(m.current.muted=!b,l(!b))},C=p=>{m.current&&(m.current.currentTime+=p)},R=p=>{if(!isFinite(p)||isNaN(p)||p<0)return"0:00";const k=Math.floor(p/60),v=Math.floor(p%60);return`${k}:${v.toString().padStart(2,"0")}`},L=()=>{c("音频加载失败")};return o?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:o})})}):e.jsxs("div",{className:"flex flex-col items-center justify-center w-full h-full p-8 gap-8",children:[e.jsx("div",{className:"w-64 h-64 rounded-3xl bg-gradient-to-br from-purple-500 via-pink-500 to-rose-500 flex items-center justify-center shadow-2xl backdrop-blur-xl",children:e.jsx(y.Music,{className:"w-32 h-32 text-white"})}),e.jsxs("div",{className:"text-white text-center max-w-md",children:[e.jsx("p",{className:"text-2xl font-medium mb-1",children:r}),e.jsx("p",{className:"text-sm text-white/60",children:"音频文件"})]}),e.jsxs("div",{className:"w-full max-w-md bg-white/10 backdrop-blur-xl rounded-2xl p-6 border border-white/20",children:[e.jsxs("div",{className:"mb-4",children:[e.jsxs("div",{className:"relative h-4 flex items-center",children:[e.jsx("div",{className:"absolute w-full h-[6px] bg-white/20 rounded-full"}),e.jsx("div",{className:"absolute h-[6px] bg-gradient-to-r from-purple-500 to-pink-500 rounded-full transition-all duration-100 ease-linear pointer-events-none",style:{width:`${a>0?i/a*100:i>100?100:i}%`}}),e.jsx("input",{type:"range",min:"0",max:a>0?a:100+(i>100?i%100:0),value:i,onChange:j,className:"audio-slider absolute w-full"})]}),e.jsxs("div",{className:"flex justify-between text-xs text-white/60 mt-3",children:[e.jsx("span",{children:R(i)}),e.jsx("span",{children:R(a)})]})]}),e.jsxs("div",{className:"flex items-center justify-center gap-4 mb-4",children:[e.jsx("button",{onClick:()=>C(-10),className:"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all",children:e.jsx(y.SkipBack,{className:"w-5 h-5"})}),e.jsx("button",{onClick:f,className:"w-14 h-14 rounded-full bg-gradient-to-br from-purple-500 to-pink-500 hover:scale-105 flex items-center justify-center text-white transition-all shadow-lg",children:d?e.jsx(y.Pause,{className:"w-6 h-6"}):e.jsx(y.Play,{className:"w-6 h-6 ml-1"})}),e.jsx("button",{onClick:()=>C(10),className:"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all",children:e.jsx(y.SkipForward,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{onClick:S,className:"text-white/80 hover:text-white transition-colors",children:b||x===0?e.jsx(y.VolumeX,{className:"w-5 h-5"}):e.jsx(y.Volume2,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1 relative h-3 flex items-center",children:[e.jsx("div",{className:"absolute w-full h-[4px] bg-white/20 rounded-full"}),e.jsx("div",{className:"absolute h-[4px] bg-purple-500 rounded-full transition-all duration-100 pointer-events-none",style:{width:`${(b?0:x)*100}%`}}),e.jsx("input",{type:"range",min:"0",max:"1",step:"0.01",value:b?0:x,onChange:N,className:"volume-slider absolute w-full"})]})]})]}),e.jsx("audio",{ref:m,src:s,onError:L,className:"hidden"})]})},A={'pre[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:".5em 0",overflow:"auto",background:"#1e1e1e"},'code[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'pre[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},':not(pre) > code[class*="language-"]':{padding:".1em .3em",borderRadius:".3em",color:"#db4c69",background:"#1e1e1e"},".namespace":{Opacity:".7"},"doctype.doctype-tag":{color:"#569CD6"},"doctype.name":{color:"#9cdcfe"},comment:{color:"#6a9955"},prolog:{color:"#6a9955"},punctuation:{color:"#d4d4d4"},".language-html .language-css .token.punctuation":{color:"#d4d4d4"},".language-html .language-javascript .token.punctuation":{color:"#d4d4d4"},property:{color:"#9cdcfe"},tag:{color:"#569cd6"},boolean:{color:"#569cd6"},number:{color:"#b5cea8"},constant:{color:"#9cdcfe"},symbol:{color:"#b5cea8"},inserted:{color:"#b5cea8"},unit:{color:"#b5cea8"},selector:{color:"#d7ba7d"},"attr-name":{color:"#9cdcfe"},string:{color:"#ce9178"},char:{color:"#ce9178"},builtin:{color:"#ce9178"},deleted:{color:"#ce9178"},".language-css .token.string.url":{textDecoration:"underline"},operator:{color:"#d4d4d4"},entity:{color:"#569cd6"},"operator.arrow":{color:"#569CD6"},atrule:{color:"#ce9178"},"atrule.rule":{color:"#c586c0"},"atrule.url":{color:"#9cdcfe"},"atrule.url.function":{color:"#dcdcaa"},"atrule.url.punctuation":{color:"#d4d4d4"},keyword:{color:"#569CD6"},"keyword.module":{color:"#c586c0"},"keyword.control-flow":{color:"#c586c0"},function:{color:"#dcdcaa"},"function.maybe-class-name":{color:"#dcdcaa"},regex:{color:"#d16969"},important:{color:"#569cd6"},italic:{fontStyle:"italic"},"class-name":{color:"#4ec9b0"},"maybe-class-name":{color:"#4ec9b0"},console:{color:"#9cdcfe"},parameter:{color:"#9cdcfe"},interpolation:{color:"#9cdcfe"},"punctuation.interpolation-punctuation":{color:"#569cd6"},variable:{color:"#9cdcfe"},"imports.maybe-class-name":{color:"#9cdcfe"},"exports.maybe-class-name":{color:"#9cdcfe"},escape:{color:"#d7ba7d"},"tag.punctuation":{color:"#808080"},cdata:{color:"#808080"},"attr-value":{color:"#ce9178"},"attr-value.punctuation":{color:"#ce9178"},"attr-value.punctuation.attr-equals":{color:"#d4d4d4"},namespace:{color:"#4ec9b0"},'pre[class*="language-javascript"]':{color:"#9cdcfe"},'code[class*="language-javascript"]':{color:"#9cdcfe"},'pre[class*="language-jsx"]':{color:"#9cdcfe"},'code[class*="language-jsx"]':{color:"#9cdcfe"},'pre[class*="language-typescript"]':{color:"#9cdcfe"},'code[class*="language-typescript"]':{color:"#9cdcfe"},'pre[class*="language-tsx"]':{color:"#9cdcfe"},'code[class*="language-tsx"]':{color:"#9cdcfe"},'pre[class*="language-css"]':{color:"#ce9178"},'code[class*="language-css"]':{color:"#ce9178"},'pre[class*="language-html"]':{color:"#d4d4d4"},'code[class*="language-html"]':{color:"#d4d4d4"},".language-regex .token.anchor":{color:"#dcdcaa"},".language-html .token.punctuation":{color:"#808080"},'pre[class*="language-"] > code[class*="language-"]':{position:"relative",zIndex:"1"},".line-highlight.line-highlight":{background:"#f7ebc6",boxShadow:"inset 5px 0 0 #f7d87c",zIndex:"0"}},ae=({url:s})=>{const[r,o]=t.useState(""),[c,d]=t.useState(!0),[u,i]=t.useState(null);return t.useEffect(()=>{(async()=>{try{d(!0),i(null);const a=await fetch(s);if(!a.ok)throw new Error("加载失败");const w=await a.text();o(w)}catch(a){i("Markdown 文件加载失败"),console.error(a)}finally{d(!1)}})()},[s]),c?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})}):u?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:u})})}):e.jsx("div",{className:"w-full h-full overflow-auto p-8",children:e.jsx("div",{className:"max-w-4xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl p-8 border border-white/10",children:e.jsx("div",{className:"prose prose-invert prose-lg max-w-none",children:e.jsx(_,{remarkPlugins:[Z],components:{code({node:n,inline:a,className:w,children:x,...h}){const b=/language-(\w+)/.exec(w||"");return!a&&b?e.jsx(O.Prism,{style:A,language:b[1],PreTag:"div",className:"rounded-lg",...h,children:String(x).replace(/\n$/,"")}):e.jsx("code",{className:"bg-white/10 px-1.5 py-0.5 rounded text-sm",...h,children:x})},h1:({children:n})=>e.jsx("h1",{className:"text-4xl font-bold mb-4 text-white border-b border-white/20 pb-2",children:n}),h2:({children:n})=>e.jsx("h2",{className:"text-3xl font-bold mb-3 text-white mt-8",children:n}),h3:({children:n})=>e.jsx("h3",{className:"text-2xl font-bold mb-2 text-white mt-6",children:n}),p:({children:n})=>e.jsx("p",{className:"text-white/90 mb-4 leading-relaxed",children:n}),a:({href:n,children:a})=>e.jsx("a",{href:n,className:"text-blue-400 hover:text-blue-300 underline",target:"_blank",rel:"noopener noreferrer",children:a}),ul:({children:n})=>e.jsx("ul",{className:"list-disc list-inside mb-4 text-white/90",children:n}),ol:({children:n})=>e.jsx("ol",{className:"list-decimal list-inside mb-4 text-white/90",children:n}),li:({children:n})=>e.jsx("li",{className:"mb-1",children:n}),blockquote:({children:n})=>e.jsx("blockquote",{className:"border-l-4 border-blue-500 pl-4 italic text-white/80 my-4",children:n}),table:({children:n})=>e.jsx("div",{className:"overflow-x-auto my-4",children:e.jsx("table",{className:"min-w-full border border-white/20",children:n})}),th:({children:n})=>e.jsx("th",{className:"border border-white/20 px-4 py-2 bg-white/10 text-white font-semibold",children:n}),td:({children:n})=>e.jsx("td",{className:"border border-white/20 px-4 py-2 text-white/90",children:n}),hr:()=>e.jsx("hr",{className:"border-white/20 my-6"}),img:({src:n,alt:a})=>e.jsx("img",{src:n,alt:a,className:"rounded-lg max-w-full h-auto my-4"})},children:r})})})})},ce=s=>{var c;const r=((c=s.split(".").pop())==null?void 0:c.toLowerCase())||"";return{js:"javascript",jsx:"jsx",ts:"typescript",tsx:"tsx",py:"python",java:"java",cpp:"cpp",c:"c",cs:"csharp",php:"php",rb:"ruby",go:"go",rs:"rust",swift:"swift",kt:"kotlin",scala:"scala",sh:"bash",bash:"bash",zsh:"bash",json:"json",xml:"xml",html:"html",css:"css",scss:"scss",sass:"sass",less:"less",sql:"sql",yaml:"yaml",yml:"yaml",toml:"toml",ini:"ini",conf:"nginx",md:"markdown",txt:"text"}[r]||"text"},ie=({url:s,fileName:r})=>{const[o,c]=t.useState(""),[d,u]=t.useState(!0),[i,n]=t.useState(null),a=ce(r);return t.useEffect(()=>{(async()=>{try{u(!0),n(null);const x=await fetch(s);if(!x.ok)throw new Error("加载失败");const h=await x.text();c(h)}catch(x){n("文本文件加载失败"),console.error(x)}finally{u(!1)}})()},[s]),d?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin"})}):i?e.jsx("div",{className:"flex items-center justify-center w-full h-full",children:e.jsx("div",{className:"text-white/70 text-center",children:e.jsx("p",{className:"text-lg",children:i})})}):e.jsx("div",{className:"w-full h-full overflow-auto p-8",children:e.jsxs("div",{className:"max-w-6xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl border border-white/10 overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-3 px-6 py-4 bg-white/5 border-b border-white/10",children:[e.jsx(y.FileText,{className:"w-5 h-5 text-white/70"}),e.jsx("span",{className:"text-white font-medium",children:r}),e.jsx("span",{className:"ml-auto text-xs text-white/50 uppercase",children:a})]}),e.jsx("div",{className:"text-sm",children:a==="text"?e.jsx("pre",{className:"p-6 text-white/90 font-mono whitespace-pre-wrap break-words",children:o}):e.jsx(O.Prism,{language:a,style:A,showLineNumbers:!0,customStyle:{margin:0,padding:"1.5rem",background:"transparent",fontSize:"0.875rem"},lineNumberStyle:{minWidth:"3em",paddingRight:"1em",color:"rgba(255, 255, 255, 0.3)",userSelect:"none"},children:o})})]})})},de=({fileName:s,fileType:r,onDownload:o})=>e.jsxs("div",{className:"flex flex-col items-center justify-center w-full h-full p-8 gap-6",children:[e.jsx("div",{className:"w-32 h-32 rounded-full bg-white/10 flex items-center justify-center",children:e.jsx(y.FileQuestion,{className:"w-16 h-16 text-white/70"})}),e.jsxs("div",{className:"text-white text-center",children:[e.jsx("p",{className:"text-xl font-medium mb-2",children:s}),e.jsxs("p",{className:"text-white/70",children:["不支持预览此文件类型 (",r,")"]})]}),e.jsxs("button",{onClick:o,className:"flex items-center gap-2 px-6 py-3 bg-white/10 hover:bg-white/20 backdrop-blur-sm rounded-lg text-white font-medium transition-all",children:[e.jsx(y.Download,{className:"w-5 h-5"}),"下载文件查看"]})]}),ue=s=>{var d;const r=((d=s.name.split(".").pop())==null?void 0:d.toLowerCase())||"",o=s.type.toLowerCase();if(o.startsWith("image/")||["jpg","jpeg","png","gif","webp","svg"].includes(r))return"image";if(o.includes("pdf")||r==="pdf")return"pdf";if(o.includes("wordprocessingml")||r==="docx")return"docx";if(o.includes("spreadsheetml")||r==="xlsx")return"xlsx";if(o.includes("presentationml")||r==="pptx"||r==="ppt")return"pptx";if(o.startsWith("video/")||["mp4","webm","ogg","ogv","mov","avi","mkv","m4v","3gp","flv"].includes(r))return"video";if(o.startsWith("audio/")||["mp3","wav","ogg","m4a","flac","aac"].includes(r))return"audio";if(r==="md"||r==="markdown")return"markdown";const c=["txt","log","csv","js","jsx","ts","tsx","json","py","java","cpp","c","h","cs","php","rb","go","rs","swift","kt","html","css","scss","sass","less","xml","yaml","yml","toml","ini","conf","sh","bash","zsh","sql"];return o.startsWith("text/")||c.includes(r)?"text":"unsupported"},me=({files:s,currentIndex:r,isOpen:o,onClose:c,onNavigate:d})=>{const[u,i]=t.useState(1),[n,a]=t.useState(0),[w,x]=t.useState(1),[,h]=t.useState(1),b=t.useMemo(()=>B(s),[s]),l=b[r],m=l?ue(l):"unsupported";t.useEffect(()=>{i(1),a(0),x(1),h(1)},[r]),t.useEffect(()=>{if(o){const g=document.body.style.overflow,T=document.body.style.paddingRight,F=window.innerWidth-document.documentElement.clientWidth;return document.body.style.overflow="hidden",F>0&&(document.body.style.paddingRight=`${F}px`),()=>{document.body.style.overflow=g,document.body.style.paddingRight=T}}},[o]),t.useEffect(()=>{if(!o)return;const g=T=>{T.key==="Escape"?c():T.key==="ArrowLeft"&&r>0?d==null||d(r-1):T.key==="ArrowRight"&&r<b.length-1&&(d==null||d(r+1))};return window.addEventListener("keydown",g),()=>window.removeEventListener("keydown",g)},[o,r,b.length,c,d]);const f=t.useCallback(()=>{i(g=>Math.min(g+.25,5))},[]),j=t.useCallback(()=>{i(g=>Math.max(g-.25,.5))},[]),N=t.useCallback(()=>{a(g=>g+90)},[]),S=t.useCallback(()=>{a(g=>g-90)},[]),C=t.useCallback(()=>{i(1),a(0)},[]),R=t.useCallback(()=>{i(1)},[]),L=t.useCallback(g=>{i(g)},[]),p=t.useCallback(()=>{i(1),a(0)},[]),k=t.useCallback(()=>{if(!l)return;const g=document.createElement("a");g.href=l.url,g.download=l.name,g.click()},[l]);if(!o||!l)return null;const v=m==="image"||m==="pdf",E=m==="image";return e.jsx(D.AnimatePresence,{children:o&&e.jsx(D.motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md overflow-hidden",onClick:c,onWheel:g=>g.stopPropagation(),children:e.jsxs("div",{className:"relative w-full h-full flex flex-col overflow-hidden",onClick:g=>g.stopPropagation(),children:[e.jsx(D.motion.div,{initial:{y:-100},animate:{y:0},exit:{y:-100},className:"absolute top-0 left-0 right-0 z-10 p-4",children:e.jsxs("div",{className:"max-w-7xl mx-auto flex items-center justify-between bg-black/40 backdrop-blur-xl rounded-2xl px-6 py-4 shadow-2xl border border-white/10",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("h2",{className:"text-white font-medium text-lg truncate",children:l.name}),e.jsxs("p",{className:"text-white/60 text-sm",children:[r+1," / ",b.length]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-4",children:[v&&e.jsxs(e.Fragment,{children:[e.jsx(M,{icon:e.jsx(y.ZoomOut,{className:"w-5 h-5"}),label:"缩小",onClick:j,disabled:u<=.5}),e.jsxs("span",{className:"text-white/70 text-sm min-w-[4rem] text-center font-medium",children:[Math.round(u*100),"%"]}),e.jsx(M,{icon:e.jsx(y.ZoomIn,{className:"w-5 h-5"}),label:"放大",onClick:f,disabled:u>=5}),e.jsx("div",{className:"w-px h-6 bg-white/20 mx-2"}),e.jsx(M,{icon:e.jsx(y.Minimize2,{className:"w-5 h-5"}),label:"适应窗口",onClick:C}),e.jsx(M,{icon:e.jsx(y.Maximize2,{className:"w-5 h-5"}),label:"原始尺寸",onClick:R}),e.jsx("div",{className:"w-px h-6 bg-white/20 mx-2"})]}),E&&e.jsxs(e.Fragment,{children:[e.jsx(M,{icon:e.jsx(y.RotateCcw,{className:"w-5 h-5"}),label:"向左旋转",onClick:S}),e.jsx(M,{icon:e.jsx(y.RotateCw,{className:"w-5 h-5"}),label:"向右旋转",onClick:N}),e.jsx("div",{className:"w-px h-6 bg-white/20 mx-2"})]}),(v||E)&&e.jsxs(e.Fragment,{children:[e.jsx(M,{icon:e.jsx(y.RefreshCw,{className:"w-5 h-5"}),label:"复原",onClick:p}),e.jsx("div",{className:"w-px h-6 bg-white/20 mx-2"})]}),e.jsx(M,{icon:e.jsx(y.Download,{className:"w-5 h-5"}),label:"下载",onClick:k}),e.jsx("div",{className:"w-px h-6 bg-white/20 mx-2"}),e.jsx(M,{icon:e.jsx(y.X,{className:"w-5 h-5"}),label:"关闭",onClick:c})]})]})}),e.jsxs("div",{className:"flex-1 flex items-center justify-center pt-24 pb-8 overflow-auto",children:[m==="image"&&e.jsx(Y,{url:l.url,zoom:u,rotation:n,onZoomChange:L}),m==="pdf"&&e.jsx(ee,{url:l.url,zoom:u,currentPage:w,onPageChange:x,onTotalPagesChange:h}),m==="docx"&&e.jsx(te,{url:l.url}),m==="xlsx"&&e.jsx(se,{url:l.url}),m==="pptx"&&e.jsx(re,{url:l.url}),m==="video"&&e.jsx(ne,{url:l.url}),m==="audio"&&e.jsx(le,{url:l.url,fileName:l.name}),m==="markdown"&&e.jsx(ae,{url:l.url}),m==="text"&&e.jsx(ie,{url:l.url,fileName:l.name}),m==="unsupported"&&e.jsx(de,{fileName:l.name,fileType:l.type,onDownload:k})]}),b.length>1&&e.jsxs(e.Fragment,{children:[r>0&&e.jsx(D.motion.button,{initial:{x:-100,opacity:0},animate:{x:0,opacity:1},exit:{x:-100,opacity:0},onClick:()=>d==null?void 0:d(r-1),className:"absolute left-4 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-black/40 backdrop-blur-xl border border-white/10 flex items-center justify-center text-white hover:bg-black/60 transition-all shadow-2xl",children:e.jsx(y.ChevronLeft,{className:"w-6 h-6"})}),r<b.length-1&&e.jsx(D.motion.button,{initial:{x:100,opacity:0},animate:{x:0,opacity:1},exit:{x:100,opacity:0},onClick:()=>d==null?void 0:d(r+1),className:"absolute right-4 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-black/40 backdrop-blur-xl border border-white/10 flex items-center justify-center text-white hover:bg-black/60 transition-all shadow-2xl",children:e.jsx(y.ChevronRight,{className:"w-6 h-6"})})]})]})})})},M=({icon:s,label:r,onClick:o,disabled:c})=>e.jsx("button",{onClick:o,disabled:c,title:r,className:`p-2 rounded-lg transition-all ${c?"text-white/30 cursor-not-allowed":"text-white hover:bg-white/10 active:bg-white/20"}`,children:s});exports.FilePreviewModal=me;exports.normalizeFile=H;exports.normalizeFiles=B;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|