@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.
Files changed (39) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +384 -0
  3. package/README.zh-CN.md +383 -0
  4. package/lib/FilePreviewModal.d.ts +11 -0
  5. package/lib/FilePreviewModal.d.ts.map +1 -0
  6. package/lib/index.cjs +2 -0
  7. package/lib/index.cjs.map +1 -0
  8. package/lib/index.css +1 -0
  9. package/lib/index.d.ts +4 -0
  10. package/lib/index.d.ts.map +1 -0
  11. package/lib/index.mjs +1478 -0
  12. package/lib/index.mjs.map +1 -0
  13. package/lib/renderers/AudioRenderer.d.ts +7 -0
  14. package/lib/renderers/AudioRenderer.d.ts.map +1 -0
  15. package/lib/renderers/DocxRenderer.d.ts +6 -0
  16. package/lib/renderers/DocxRenderer.d.ts.map +1 -0
  17. package/lib/renderers/ImageRenderer.d.ts +9 -0
  18. package/lib/renderers/ImageRenderer.d.ts.map +1 -0
  19. package/lib/renderers/MarkdownRenderer.d.ts +6 -0
  20. package/lib/renderers/MarkdownRenderer.d.ts.map +1 -0
  21. package/lib/renderers/PdfRenderer.d.ts +13 -0
  22. package/lib/renderers/PdfRenderer.d.ts.map +1 -0
  23. package/lib/renderers/PptxRenderer.d.ts +6 -0
  24. package/lib/renderers/PptxRenderer.d.ts.map +1 -0
  25. package/lib/renderers/TextRenderer.d.ts +7 -0
  26. package/lib/renderers/TextRenderer.d.ts.map +1 -0
  27. package/lib/renderers/UnsupportedRenderer.d.ts +8 -0
  28. package/lib/renderers/UnsupportedRenderer.d.ts.map +1 -0
  29. package/lib/renderers/VideoRenderer.d.ts +7 -0
  30. package/lib/renderers/VideoRenderer.d.ts.map +1 -0
  31. package/lib/renderers/XlsxRenderer.d.ts +6 -0
  32. package/lib/renderers/XlsxRenderer.d.ts.map +1 -0
  33. package/lib/types.d.ts +29 -0
  34. package/lib/types.d.ts.map +1 -0
  35. package/lib/utils/fileNormalizer.d.ts +14 -0
  36. package/lib/utils/fileNormalizer.d.ts.map +1 -0
  37. package/lib/utils/pdfConfig.d.ts +3 -0
  38. package/lib/utils/pdfConfig.d.ts.map +1 -0
  39. package/package.json +113 -0
@@ -0,0 +1,383 @@
1
+ # React File Preview [![npm version](https://img.shields.io/npm/v/@eternalheart/react-file-preview.svg)](https://www.npmjs.com/package/@eternalheart/react-file-preview)[![license](https://img.shields.io/npm/l/@eternalheart/react-file-preview.svg)](https://github.com/wh131462/react-file-preview/blob/master/LICENSE)[![downloads](https://img.shields.io/npm/dm/@eternalheart/react-file-preview.svg)](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