@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
package/lib/index.mjs ADDED
@@ -0,0 +1,1478 @@
1
+ import { jsxs as p, jsx as e, Fragment as $ } from "react/jsx-runtime";
2
+ import { useState as w, useRef as S, useEffect as M, useCallback as C, useMemo as Z } from "react";
3
+ import { motion as F, AnimatePresence as _ } from "framer-motion";
4
+ import { Presentation as G, Music as I, SkipBack as Y, Pause as K, Play as Q, SkipForward as J, VolumeX as ee, Volume2 as te, FileText as re, FileQuestion as oe, Download as V, ZoomOut as ne, ZoomIn as le, Minimize2 as ae, Maximize2 as se, RotateCcw as ie, RotateCw as ce, RefreshCw as de, X as me, ChevronLeft as ue, ChevronRight as he } from "lucide-react";
5
+ import { pdfjs as W, Document as pe, Page as fe } from "react-pdf";
6
+ import xe from "mammoth";
7
+ import * as A from "xlsx";
8
+ import { init as O } from "pptx-preview";
9
+ import we from "video.js";
10
+ import ge from "react-markdown";
11
+ import be from "remark-gfm";
12
+ import { Prism as X } from "react-syntax-highlighter";
13
+ function ve(r) {
14
+ try {
15
+ const i = new URL(r).pathname.split("/").pop() || "file";
16
+ return decodeURIComponent(i);
17
+ } catch {
18
+ const t = r.split("/").pop() || "file";
19
+ return decodeURIComponent(t);
20
+ }
21
+ }
22
+ function B(r) {
23
+ var i;
24
+ const t = ((i = r.split(".").pop()) == null ? void 0 : i.toLowerCase()) || "";
25
+ return {
26
+ // 图片
27
+ jpg: "image/jpeg",
28
+ jpeg: "image/jpeg",
29
+ png: "image/png",
30
+ gif: "image/gif",
31
+ webp: "image/webp",
32
+ svg: "image/svg+xml",
33
+ bmp: "image/bmp",
34
+ ico: "image/x-icon",
35
+ // 视频
36
+ mp4: "video/mp4",
37
+ webm: "video/webm",
38
+ ogg: "video/ogg",
39
+ ogv: "video/ogg",
40
+ mov: "video/quicktime",
41
+ avi: "video/x-msvideo",
42
+ mkv: "video/x-matroska",
43
+ m4v: "video/x-m4v",
44
+ "3gp": "video/3gpp",
45
+ flv: "video/x-flv",
46
+ // 音频
47
+ mp3: "audio/mpeg",
48
+ wav: "audio/wav",
49
+ m4a: "audio/mp4",
50
+ aac: "audio/aac",
51
+ flac: "audio/flac",
52
+ // 文档
53
+ pdf: "application/pdf",
54
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
55
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
56
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
57
+ ppt: "application/vnd.ms-powerpoint",
58
+ // 文本
59
+ txt: "text/plain",
60
+ md: "text/markdown",
61
+ markdown: "text/markdown",
62
+ json: "application/json",
63
+ xml: "application/xml",
64
+ html: "text/html",
65
+ css: "text/css",
66
+ js: "text/javascript",
67
+ ts: "text/typescript",
68
+ jsx: "text/javascript",
69
+ tsx: "text/typescript",
70
+ py: "text/x-python",
71
+ java: "text/x-java",
72
+ cpp: "text/x-c++src",
73
+ c: "text/x-csrc",
74
+ cs: "text/x-csharp",
75
+ php: "text/x-php",
76
+ rb: "text/x-ruby",
77
+ go: "text/x-go",
78
+ rs: "text/x-rust",
79
+ yaml: "text/yaml",
80
+ yml: "text/yaml"
81
+ }[t] || "application/octet-stream";
82
+ }
83
+ function ye(r, t = 0) {
84
+ if (r instanceof File)
85
+ return {
86
+ id: `file-${Date.now()}-${t}`,
87
+ name: r.name,
88
+ url: URL.createObjectURL(r),
89
+ type: r.type || B(r.name),
90
+ size: r.size
91
+ };
92
+ if (typeof r == "string") {
93
+ const n = ve(r);
94
+ return {
95
+ id: `url-${Date.now()}-${t}`,
96
+ name: n,
97
+ url: r,
98
+ type: B(n)
99
+ };
100
+ }
101
+ return {
102
+ id: r.id || `link-${Date.now()}-${t}`,
103
+ name: r.name,
104
+ url: r.url,
105
+ type: r.type || B(r.name),
106
+ size: r.size
107
+ };
108
+ }
109
+ function Ne(r) {
110
+ return r.map((t, n) => ye(t, n));
111
+ }
112
+ const ke = ({
113
+ url: r,
114
+ zoom: t,
115
+ rotation: n,
116
+ onZoomChange: i
117
+ }) => {
118
+ const [c, d] = w(!1), [s, o] = w(null), [a, g] = w({ x: 0, y: 0 }), [u, h] = w(!1), [v, l] = w({ x: 0, y: 0 }), [m, f] = w(1), y = S(null);
119
+ M(() => {
120
+ d(!1), o(null), g({ x: 0, y: 0 }), f(1);
121
+ }, [r]), M(() => {
122
+ f(t);
123
+ }, [t]), M(() => {
124
+ g({ x: 0, y: 0 });
125
+ }, [t, n]);
126
+ const k = () => {
127
+ d(!0);
128
+ }, T = () => {
129
+ o("图片加载失败"), d(!0);
130
+ }, L = () => {
131
+ g({ x: 0, y: 0 });
132
+ }, P = C((N) => {
133
+ N.preventDefault(), N.stopPropagation();
134
+ const R = N.deltaY > 0 ? -0.1 : 0.1;
135
+ f((b) => {
136
+ const E = Math.max(0.5, Math.min(5, b + R));
137
+ return i && i(E), E;
138
+ });
139
+ }, [i]), z = C((N) => {
140
+ N.button === 0 && (h(!0), l({
141
+ x: N.clientX - a.x,
142
+ y: N.clientY - a.y
143
+ }));
144
+ }, [a]), x = C((N) => {
145
+ u && g({
146
+ x: N.clientX - v.x,
147
+ y: N.clientY - v.y
148
+ });
149
+ }, [u, v]), j = C(() => {
150
+ h(!1);
151
+ }, []);
152
+ return /* @__PURE__ */ p(
153
+ "div",
154
+ {
155
+ ref: y,
156
+ className: "flex items-center justify-center w-full h-full overflow-hidden",
157
+ onWheel: P,
158
+ onMouseDown: z,
159
+ onMouseMove: x,
160
+ onMouseUp: j,
161
+ onMouseLeave: j,
162
+ style: { cursor: u ? "grabbing" : "grab" },
163
+ children: [
164
+ !c && !s && /* @__PURE__ */ e("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }),
165
+ s && /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: s }) }),
166
+ /* @__PURE__ */ e(
167
+ F.img,
168
+ {
169
+ src: r,
170
+ alt: "Preview",
171
+ className: `max-w-none select-none ${c ? "" : "hidden"}`,
172
+ style: {
173
+ transform: `translate(${a.x}px, ${a.y}px) scale(${m}) rotate(${n}deg)`,
174
+ transformOrigin: "center",
175
+ transition: u ? "none" : "transform 0.3s ease-out"
176
+ },
177
+ onLoad: k,
178
+ onError: T,
179
+ onDoubleClick: L,
180
+ initial: { opacity: 0 },
181
+ animate: { opacity: c ? 1 : 0 },
182
+ transition: { duration: 0.3 },
183
+ draggable: !1
184
+ }
185
+ )
186
+ ]
187
+ }
188
+ );
189
+ }, je = W.version, Ce = "/pdf.worker.min.mjs";
190
+ W.GlobalWorkerOptions.workerSrc = Ce;
191
+ const Me = W.GlobalWorkerOptions.workerSrc, U = `https://unpkg.com/pdfjs-dist@${je}/build/pdf.worker.min.mjs`;
192
+ typeof window < "u" && window.addEventListener("error", (r) => {
193
+ var t;
194
+ (t = r.message) != null && t.includes("pdf.worker") && W.GlobalWorkerOptions.workerSrc === Me && (console.warn("本地 PDF worker 加载失败,切换到 CDN:", U), W.GlobalWorkerOptions.workerSrc = U);
195
+ });
196
+ const Te = ({
197
+ url: r,
198
+ zoom: t,
199
+ currentPage: n,
200
+ onPageChange: i,
201
+ onTotalPagesChange: c
202
+ }) => {
203
+ const [d, s] = w(0), [o, a] = w(null), g = S(null), u = S(/* @__PURE__ */ new Map());
204
+ M(() => {
205
+ a(null);
206
+ }, [r]);
207
+ const h = ({ numPages: f }) => {
208
+ s(f), c(f), i(1);
209
+ }, v = (f) => {
210
+ console.error("PDF 加载错误:", f), a("PDF 文件加载失败");
211
+ }, l = C(() => {
212
+ if (!g.current) return;
213
+ const f = g.current, y = f.scrollTop, k = f.clientHeight, T = y + k / 2;
214
+ let L = 1, P = 1 / 0;
215
+ u.current.forEach((z, x) => {
216
+ const j = z.getBoundingClientRect(), N = f.getBoundingClientRect(), R = j.top - N.top + j.height / 2 + y, b = Math.abs(R - T);
217
+ b < P && (P = b, L = x);
218
+ }), L !== n && i(L);
219
+ }, [n, i]);
220
+ M(() => {
221
+ const f = g.current;
222
+ if (f)
223
+ return f.addEventListener("scroll", l), () => f.removeEventListener("scroll", l);
224
+ }, [l]);
225
+ const m = C((f, y) => {
226
+ y ? u.current.set(f, y) : u.current.delete(f);
227
+ }, []);
228
+ return /* @__PURE__ */ p(
229
+ "div",
230
+ {
231
+ ref: g,
232
+ className: "flex flex-col items-center w-full h-full overflow-auto py-8 px-4",
233
+ children: [
234
+ o && /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: o }) }),
235
+ !o && /* @__PURE__ */ e(
236
+ pe,
237
+ {
238
+ file: r,
239
+ onLoadSuccess: h,
240
+ onLoadError: v,
241
+ loading: /* @__PURE__ */ e("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }),
242
+ children: /* @__PURE__ */ e("div", { className: "flex flex-col gap-4", children: Array.from(new Array(d), (f, y) => {
243
+ const k = y + 1;
244
+ return /* @__PURE__ */ p(
245
+ "div",
246
+ {
247
+ ref: (T) => m(k, T),
248
+ className: "relative",
249
+ children: [
250
+ /* @__PURE__ */ e(
251
+ fe,
252
+ {
253
+ pageNumber: k,
254
+ scale: t,
255
+ loading: /* @__PURE__ */ e("div", { className: "flex items-center justify-center p-8 bg-white/5 rounded-lg min-h-[600px]", children: /* @__PURE__ */ e("div", { className: "w-8 h-8 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }),
256
+ renderTextLayer: !0,
257
+ renderAnnotationLayer: !0,
258
+ className: "shadow-2xl"
259
+ }
260
+ ),
261
+ /* @__PURE__ */ e("div", { className: "absolute top-2 right-2 bg-black/60 backdrop-blur-sm text-white text-xs px-3 py-1 rounded-full", children: k })
262
+ ]
263
+ },
264
+ `page_${k}`
265
+ );
266
+ }) })
267
+ }
268
+ ),
269
+ d > 0 && /* @__PURE__ */ p("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: [
270
+ "第 ",
271
+ n,
272
+ " 页 / 共 ",
273
+ d,
274
+ " 页"
275
+ ] })
276
+ ]
277
+ }
278
+ );
279
+ }, Le = ({ url: r }) => {
280
+ const [t, n] = w(""), [i, c] = w(!0), [d, s] = w(null);
281
+ return M(() => {
282
+ (async () => {
283
+ c(!0), s(null), n("");
284
+ try {
285
+ const a = await fetch(r);
286
+ if (!a.ok)
287
+ throw new Error("文件加载失败");
288
+ const g = await a.arrayBuffer(), u = await xe.convertToHtml({ arrayBuffer: g });
289
+ n(u.value);
290
+ } catch (a) {
291
+ console.error("Docx 解析错误:", a), s("Word 文档解析失败");
292
+ } finally {
293
+ c(!1);
294
+ }
295
+ })();
296
+ }, [r]), i ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }) : d ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: d }) }) }) : /* @__PURE__ */ e("div", { className: "w-full h-full overflow-auto p-8", children: /* @__PURE__ */ e(
297
+ "div",
298
+ {
299
+ className: "max-w-4xl mx-auto bg-white rounded-lg shadow-2xl p-12",
300
+ dangerouslySetInnerHTML: { __html: t },
301
+ style: {
302
+ fontFamily: "system-ui, -apple-system, sans-serif",
303
+ lineHeight: "1.6",
304
+ color: "#333"
305
+ }
306
+ }
307
+ ) });
308
+ }, Se = ({ url: r }) => {
309
+ const [t, n] = w([]), [i, c] = w(0), [d, s] = w(!0), [o, a] = w(null);
310
+ if (M(() => {
311
+ (async () => {
312
+ s(!0), a(null), n([]);
313
+ try {
314
+ const h = await fetch(r);
315
+ if (!h.ok)
316
+ throw new Error("文件加载失败");
317
+ const v = await h.arrayBuffer(), l = A.read(v, { type: "array" }), m = l.SheetNames.map((f) => {
318
+ const y = l.Sheets[f], k = A.utils.sheet_to_json(y, { header: 1 });
319
+ return { name: f, data: k };
320
+ });
321
+ n(m), c(0);
322
+ } catch (h) {
323
+ console.error("Excel 解析错误:", h), a("Excel 文件解析失败");
324
+ } finally {
325
+ s(!1);
326
+ }
327
+ })();
328
+ }, [r]), d)
329
+ return /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) });
330
+ if (o)
331
+ return /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: o }) }) });
332
+ const g = t[i];
333
+ return /* @__PURE__ */ p("div", { className: "w-full h-full flex flex-col overflow-hidden", children: [
334
+ t.length > 1 && /* @__PURE__ */ e("div", { className: "flex gap-2 p-4 bg-black/20 backdrop-blur-sm overflow-x-auto border-b border-white/10", children: t.map((u, h) => /* @__PURE__ */ e(
335
+ "button",
336
+ {
337
+ onClick: () => c(h),
338
+ className: `px-4 py-2 rounded-lg text-sm font-medium transition-all ${i === h ? "bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-lg" : "bg-white/10 text-white hover:bg-white/20"}`,
339
+ children: u.name
340
+ },
341
+ h
342
+ )) }),
343
+ /* @__PURE__ */ e("div", { className: "flex-1 overflow-auto p-8", children: /* @__PURE__ */ e("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: /* @__PURE__ */ e("table", { className: "min-w-full divide-y divide-white/10", children: /* @__PURE__ */ e("tbody", { className: "divide-y divide-white/10", children: g == null ? void 0 : g.data.map((u, h) => /* @__PURE__ */ e(
344
+ "tr",
345
+ {
346
+ className: `transition-colors ${h === 0 ? "bg-gradient-to-r from-purple-500/20 to-pink-500/20 font-semibold" : "hover:bg-white/5"}`,
347
+ children: u.map((v, l) => /* @__PURE__ */ e(
348
+ "td",
349
+ {
350
+ className: "px-6 py-4 whitespace-nowrap text-sm text-gray-200 border-r border-white/10",
351
+ children: String(v ?? "")
352
+ },
353
+ l
354
+ ))
355
+ },
356
+ h
357
+ )) }) }) }) })
358
+ ] });
359
+ }, Pe = ({ url: r }) => {
360
+ const [t, n] = w(!0), [i, c] = w(null), d = S(null), s = S(null), o = S(null), a = S(null), g = S(null), u = S({ width: 0, height: 0 }), h = C(() => {
361
+ if (!d.current) return { width: 960, height: 540 };
362
+ const l = d.current.clientWidth, m = Math.floor(l * 9 / 16);
363
+ return console.log("计算尺寸:", { width: l, height: m }), { width: l, height: m };
364
+ }, []), v = C(async () => {
365
+ if (!(!d.current || !a.current)) {
366
+ console.log("重新初始化预览器...");
367
+ try {
368
+ if (s.current)
369
+ try {
370
+ s.current.destroy();
371
+ } catch (f) {
372
+ console.error("销毁预览器失败:", f);
373
+ }
374
+ d.current.innerHTML = "";
375
+ const l = h();
376
+ console.log("重新初始化使用尺寸:", l);
377
+ const m = O(d.current, {
378
+ width: l.width,
379
+ height: l.height
380
+ });
381
+ s.current = m, await m.preview(a.current), console.log("重新初始化成功");
382
+ } catch (l) {
383
+ console.error("重新初始化失败:", l);
384
+ }
385
+ }
386
+ }, [h]);
387
+ return M(() => {
388
+ if (!d.current) return;
389
+ let l = !0;
390
+ const m = () => {
391
+ if (l) {
392
+ l = !1;
393
+ const L = h();
394
+ u.current = L;
395
+ return;
396
+ }
397
+ const f = h(), y = u.current, k = Math.abs(y.width - f.width), T = Math.abs(y.height - f.height);
398
+ if (k < 10 && T < 10) {
399
+ console.log("尺寸变化太小,忽略");
400
+ return;
401
+ }
402
+ console.log("检测到尺寸变化:", {
403
+ old: y,
404
+ new: f,
405
+ diff: { width: k, height: T }
406
+ }), u.current = f, g.current && clearTimeout(g.current), g.current = window.setTimeout(() => {
407
+ s.current && a.current && (console.log("尺寸变化,准备重新初始化"), v());
408
+ }, 800);
409
+ };
410
+ return o.current = new ResizeObserver(() => {
411
+ m();
412
+ }), o.current.observe(d.current), () => {
413
+ o.current && o.current.disconnect(), g.current && clearTimeout(g.current);
414
+ };
415
+ }, [h, v]), M(() => {
416
+ let l = !0;
417
+ const m = async () => {
418
+ if (!d.current) {
419
+ console.log("Container ref not ready");
420
+ return;
421
+ }
422
+ n(!0), c(null);
423
+ try {
424
+ console.log("开始加载 PPTX:", r);
425
+ const y = await fetch(r);
426
+ if (!y.ok)
427
+ throw new Error("文件加载失败");
428
+ const k = await y.arrayBuffer();
429
+ if (a.current = k, console.log("文件加载成功,大小:", k.byteLength), !l) return;
430
+ d.current && (d.current.innerHTML = "");
431
+ const T = h();
432
+ console.log("使用尺寸:", T), console.log("初始化预览器...");
433
+ const L = O(d.current, {
434
+ width: T.width,
435
+ height: T.height
436
+ });
437
+ s.current = L, console.log("开始预览..."), L.preview(k).then(() => {
438
+ console.log("预览成功"), l && n(!1);
439
+ }).catch((P) => {
440
+ console.error("预览失败:", P), l && (c("PPT 文件预览失败"), n(!1));
441
+ });
442
+ } catch (y) {
443
+ console.error("PPTX 解析错误:", y), l && (c(y instanceof Error ? y.message : "PPT 文件解析失败"), n(!1));
444
+ }
445
+ }, f = setTimeout(() => {
446
+ m();
447
+ }, 100);
448
+ return () => {
449
+ if (l = !1, clearTimeout(f), a.current = null, s.current)
450
+ try {
451
+ s.current.destroy();
452
+ } catch (y) {
453
+ console.error("销毁预览器失败:", y);
454
+ }
455
+ s.current = null;
456
+ };
457
+ }, [r, h]), /* @__PURE__ */ p("div", { className: "relative flex flex-col items-center w-full h-full pt-[8px]", children: [
458
+ t && /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl", children: /* @__PURE__ */ p("div", { className: "text-center", children: [
459
+ /* @__PURE__ */ e("div", { className: "w-12 h-12 mx-auto mb-3 border-4 border-white/20 border-t-white rounded-full animate-spin" }),
460
+ /* @__PURE__ */ e("p", { className: "text-sm text-white/70 font-medium", children: "加载 PPT 中..." })
461
+ ] }) }),
462
+ i && /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl", children: /* @__PURE__ */ p("div", { className: "text-center max-w-md", children: [
463
+ /* @__PURE__ */ e("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: /* @__PURE__ */ e(G, { className: "w-16 h-16 text-white" }) }),
464
+ /* @__PURE__ */ e("p", { className: "text-xl text-white/90 mb-3 font-medium", children: "PPT 预览" }),
465
+ /* @__PURE__ */ e("p", { className: "text-sm text-white/60 mb-6", children: i || "浏览器暂不支持直接预览 PPT 文件" }),
466
+ /* @__PURE__ */ p(
467
+ "a",
468
+ {
469
+ href: r,
470
+ download: !0,
471
+ 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",
472
+ children: [
473
+ /* @__PURE__ */ e("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("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" }) }),
474
+ "下载文件"
475
+ ]
476
+ }
477
+ ),
478
+ /* @__PURE__ */ e("p", { className: "text-xs text-white/40 mt-4", children: "提示:可以使用 Microsoft PowerPoint 或 WPS 打开" })
479
+ ] }) }),
480
+ /* @__PURE__ */ e(
481
+ "div",
482
+ {
483
+ ref: d,
484
+ className: "pptx-wrapper w-full max-w-6xl"
485
+ }
486
+ )
487
+ ] });
488
+ }, Re = (r) => {
489
+ var i;
490
+ const t = ((i = r.split(".").pop()) == null ? void 0 : i.toLowerCase().split("?")[0]) || "";
491
+ return {
492
+ mp4: "video/mp4",
493
+ webm: "video/webm",
494
+ ogg: "video/ogg",
495
+ ogv: "video/ogg",
496
+ mov: "video/quicktime",
497
+ // MOV 使用 QuickTime MIME 类型
498
+ avi: "video/x-msvideo",
499
+ mkv: "video/x-matroska",
500
+ m4v: "video/mp4",
501
+ "3gp": "video/3gpp",
502
+ flv: "video/x-flv"
503
+ }[t] || "video/mp4";
504
+ }, De = ({ url: r }) => {
505
+ const [t, n] = w(null), [i, c] = w(!0), d = S(null), s = S(null);
506
+ return M(() => {
507
+ if (!s.current && d.current) {
508
+ const o = document.createElement("video-js");
509
+ o.classList.add("vjs-big-play-centered", "vjs-theme-apple"), d.current.appendChild(o);
510
+ const a = Re(r), u = we(o, {
511
+ controls: !0,
512
+ responsive: !0,
513
+ fluid: !0,
514
+ preload: "auto",
515
+ controlBar: {
516
+ children: [
517
+ "playToggle",
518
+ "volumePanel",
519
+ "currentTimeDisplay",
520
+ "timeDivider",
521
+ "durationDisplay",
522
+ "progressControl",
523
+ "remainingTimeDisplay",
524
+ "fullscreenToggle"
525
+ ],
526
+ volumePanel: {
527
+ inline: !1
528
+ }
529
+ },
530
+ html5: {
531
+ vhs: {
532
+ overrideNative: !0
533
+ },
534
+ nativeVideoTracks: !1,
535
+ nativeAudioTracks: !1,
536
+ nativeTextTracks: !1
537
+ },
538
+ sources: a === "video/quicktime" ? [
539
+ { src: r, type: "video/quicktime" },
540
+ { src: r, type: "video/mp4" }
541
+ // 备用方案
542
+ ] : [{ src: r, type: a }]
543
+ });
544
+ u.on("loadeddata", () => {
545
+ c(!1);
546
+ }), u.on("error", () => {
547
+ const h = u.error();
548
+ console.error("Video.js error:", h), n(`视频加载失败: ${(h == null ? void 0 : h.message) || "未知错误"}`), c(!1);
549
+ }), s.current = u;
550
+ }
551
+ }, [r]), M(() => {
552
+ const o = s.current;
553
+ return () => {
554
+ o && !o.isDisposed() && (o.dispose(), s.current = null);
555
+ };
556
+ }, []), t ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ p("div", { className: "text-center", children: [
557
+ /* @__PURE__ */ e("div", { className: "w-16 h-16 mx-auto mb-4 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ e("svg", { className: "w-8 h-8 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ e("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" }) }) }),
558
+ /* @__PURE__ */ e("p", { className: "text-lg font-medium text-white/90 mb-2", children: "视频加载失败" }),
559
+ /* @__PURE__ */ e("p", { className: "text-sm text-white/60", children: t })
560
+ ] }) }) : /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full p-8", children: /* @__PURE__ */ p("div", { className: "w-full max-w-5xl relative", children: [
561
+ i && /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded-2xl z-10", children: /* @__PURE__ */ p("div", { className: "text-center", children: [
562
+ /* @__PURE__ */ e("div", { className: "w-12 h-12 mx-auto mb-3 border-3 border-white/20 border-t-white rounded-full animate-spin" }),
563
+ /* @__PURE__ */ e("p", { className: "text-sm text-white/70 font-medium", children: "加载视频中..." })
564
+ ] }) }),
565
+ /* @__PURE__ */ e(
566
+ "div",
567
+ {
568
+ ref: d,
569
+ className: "overflow-hidden",
570
+ style: {
571
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)"
572
+ }
573
+ }
574
+ )
575
+ ] }) });
576
+ }, Ee = ({ url: r, fileName: t }) => {
577
+ const [n, i] = w(null), [c, d] = w(!1), [s, o] = w(0), [a, g] = w(0), [u, h] = w(1), [v, l] = w(!1), m = S(null);
578
+ M(() => {
579
+ const x = m.current;
580
+ if (!x) return;
581
+ const j = () => {
582
+ isNaN(x.currentTime) || o(x.currentTime);
583
+ }, N = () => {
584
+ !isNaN(x.duration) && isFinite(x.duration) && g(x.duration);
585
+ }, R = () => d(!1), b = () => N();
586
+ return x.addEventListener("timeupdate", j), x.addEventListener("loadedmetadata", N), x.addEventListener("durationchange", N), x.addEventListener("canplay", b), x.addEventListener("ended", R), x.readyState >= 1 && N(), () => {
587
+ x.removeEventListener("timeupdate", j), x.removeEventListener("loadedmetadata", N), x.removeEventListener("durationchange", N), x.removeEventListener("canplay", b), x.removeEventListener("ended", R);
588
+ };
589
+ }, []);
590
+ const f = () => {
591
+ m.current && (c ? m.current.pause() : m.current.play(), d(!c));
592
+ }, y = (x) => {
593
+ const j = parseFloat(x.target.value);
594
+ o(j), m.current && (m.current.currentTime = j);
595
+ }, k = (x) => {
596
+ const j = parseFloat(x.target.value);
597
+ h(j), m.current && (m.current.volume = j), j > 0 && l(!1);
598
+ }, T = () => {
599
+ m.current && (m.current.muted = !v, l(!v));
600
+ }, L = (x) => {
601
+ m.current && (m.current.currentTime += x);
602
+ }, P = (x) => {
603
+ if (!isFinite(x) || isNaN(x) || x < 0) return "0:00";
604
+ const j = Math.floor(x / 60), N = Math.floor(x % 60);
605
+ return `${j}:${N.toString().padStart(2, "0")}`;
606
+ }, z = () => {
607
+ i("音频加载失败");
608
+ };
609
+ return n ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: n }) }) }) : /* @__PURE__ */ p("div", { className: "flex flex-col items-center justify-center w-full h-full p-8 gap-8", children: [
610
+ /* @__PURE__ */ e("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: /* @__PURE__ */ e(I, { className: "w-32 h-32 text-white" }) }),
611
+ /* @__PURE__ */ p("div", { className: "text-white text-center max-w-md", children: [
612
+ /* @__PURE__ */ e("p", { className: "text-2xl font-medium mb-1", children: t }),
613
+ /* @__PURE__ */ e("p", { className: "text-sm text-white/60", children: "音频文件" })
614
+ ] }),
615
+ /* @__PURE__ */ p("div", { className: "w-full max-w-md bg-white/10 backdrop-blur-xl rounded-2xl p-6 border border-white/20", children: [
616
+ /* @__PURE__ */ p("div", { className: "mb-4", children: [
617
+ /* @__PURE__ */ p("div", { className: "relative h-4 flex items-center", children: [
618
+ /* @__PURE__ */ e("div", { className: "absolute w-full h-[6px] bg-white/20 rounded-full" }),
619
+ /* @__PURE__ */ e(
620
+ "div",
621
+ {
622
+ 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",
623
+ style: {
624
+ width: `${a > 0 ? s / a * 100 : s > 100 ? 100 : s}%`
625
+ }
626
+ }
627
+ ),
628
+ /* @__PURE__ */ e(
629
+ "input",
630
+ {
631
+ type: "range",
632
+ min: "0",
633
+ max: a > 0 ? a : 100 + (s > 100 ? s % 100 : 0),
634
+ value: s,
635
+ onChange: y,
636
+ className: "audio-slider absolute w-full"
637
+ }
638
+ )
639
+ ] }),
640
+ /* @__PURE__ */ p("div", { className: "flex justify-between text-xs text-white/60 mt-3", children: [
641
+ /* @__PURE__ */ e("span", { children: P(s) }),
642
+ /* @__PURE__ */ e("span", { children: P(a) })
643
+ ] })
644
+ ] }),
645
+ /* @__PURE__ */ p("div", { className: "flex items-center justify-center gap-4 mb-4", children: [
646
+ /* @__PURE__ */ e(
647
+ "button",
648
+ {
649
+ onClick: () => L(-10),
650
+ className: "w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all",
651
+ children: /* @__PURE__ */ e(Y, { className: "w-5 h-5" })
652
+ }
653
+ ),
654
+ /* @__PURE__ */ e(
655
+ "button",
656
+ {
657
+ onClick: f,
658
+ 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",
659
+ children: c ? /* @__PURE__ */ e(K, { className: "w-6 h-6" }) : /* @__PURE__ */ e(Q, { className: "w-6 h-6 ml-1" })
660
+ }
661
+ ),
662
+ /* @__PURE__ */ e(
663
+ "button",
664
+ {
665
+ onClick: () => L(10),
666
+ className: "w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all",
667
+ children: /* @__PURE__ */ e(J, { className: "w-5 h-5" })
668
+ }
669
+ )
670
+ ] }),
671
+ /* @__PURE__ */ p("div", { className: "flex items-center gap-3", children: [
672
+ /* @__PURE__ */ e(
673
+ "button",
674
+ {
675
+ onClick: T,
676
+ className: "text-white/80 hover:text-white transition-colors",
677
+ children: v || u === 0 ? /* @__PURE__ */ e(ee, { className: "w-5 h-5" }) : /* @__PURE__ */ e(te, { className: "w-5 h-5" })
678
+ }
679
+ ),
680
+ /* @__PURE__ */ p("div", { className: "flex-1 relative h-3 flex items-center", children: [
681
+ /* @__PURE__ */ e("div", { className: "absolute w-full h-[4px] bg-white/20 rounded-full" }),
682
+ /* @__PURE__ */ e(
683
+ "div",
684
+ {
685
+ className: "absolute h-[4px] bg-purple-500 rounded-full transition-all duration-100 pointer-events-none",
686
+ style: {
687
+ width: `${(v ? 0 : u) * 100}%`
688
+ }
689
+ }
690
+ ),
691
+ /* @__PURE__ */ e(
692
+ "input",
693
+ {
694
+ type: "range",
695
+ min: "0",
696
+ max: "1",
697
+ step: "0.01",
698
+ value: v ? 0 : u,
699
+ onChange: k,
700
+ className: "volume-slider absolute w-full"
701
+ }
702
+ )
703
+ ] })
704
+ ] })
705
+ ] }),
706
+ /* @__PURE__ */ e(
707
+ "audio",
708
+ {
709
+ ref: m,
710
+ src: r,
711
+ onError: z,
712
+ className: "hidden"
713
+ }
714
+ )
715
+ ] });
716
+ }, q = {
717
+ 'pre[class*="language-"]': {
718
+ color: "#d4d4d4",
719
+ fontSize: "13px",
720
+ textShadow: "none",
721
+ fontFamily: 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
722
+ direction: "ltr",
723
+ textAlign: "left",
724
+ whiteSpace: "pre",
725
+ wordSpacing: "normal",
726
+ wordBreak: "normal",
727
+ lineHeight: "1.5",
728
+ MozTabSize: "4",
729
+ OTabSize: "4",
730
+ tabSize: "4",
731
+ WebkitHyphens: "none",
732
+ MozHyphens: "none",
733
+ msHyphens: "none",
734
+ hyphens: "none",
735
+ padding: "1em",
736
+ margin: ".5em 0",
737
+ overflow: "auto",
738
+ background: "#1e1e1e"
739
+ },
740
+ 'code[class*="language-"]': {
741
+ color: "#d4d4d4",
742
+ fontSize: "13px",
743
+ textShadow: "none",
744
+ fontFamily: 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
745
+ direction: "ltr",
746
+ textAlign: "left",
747
+ whiteSpace: "pre",
748
+ wordSpacing: "normal",
749
+ wordBreak: "normal",
750
+ lineHeight: "1.5",
751
+ MozTabSize: "4",
752
+ OTabSize: "4",
753
+ tabSize: "4",
754
+ WebkitHyphens: "none",
755
+ MozHyphens: "none",
756
+ msHyphens: "none",
757
+ hyphens: "none"
758
+ },
759
+ 'pre[class*="language-"]::selection': {
760
+ textShadow: "none",
761
+ background: "#264F78"
762
+ },
763
+ 'code[class*="language-"]::selection': {
764
+ textShadow: "none",
765
+ background: "#264F78"
766
+ },
767
+ 'pre[class*="language-"] *::selection': {
768
+ textShadow: "none",
769
+ background: "#264F78"
770
+ },
771
+ 'code[class*="language-"] *::selection': {
772
+ textShadow: "none",
773
+ background: "#264F78"
774
+ },
775
+ ':not(pre) > code[class*="language-"]': {
776
+ padding: ".1em .3em",
777
+ borderRadius: ".3em",
778
+ color: "#db4c69",
779
+ background: "#1e1e1e"
780
+ },
781
+ ".namespace": {
782
+ Opacity: ".7"
783
+ },
784
+ "doctype.doctype-tag": {
785
+ color: "#569CD6"
786
+ },
787
+ "doctype.name": {
788
+ color: "#9cdcfe"
789
+ },
790
+ comment: {
791
+ color: "#6a9955"
792
+ },
793
+ prolog: {
794
+ color: "#6a9955"
795
+ },
796
+ punctuation: {
797
+ color: "#d4d4d4"
798
+ },
799
+ ".language-html .language-css .token.punctuation": {
800
+ color: "#d4d4d4"
801
+ },
802
+ ".language-html .language-javascript .token.punctuation": {
803
+ color: "#d4d4d4"
804
+ },
805
+ property: {
806
+ color: "#9cdcfe"
807
+ },
808
+ tag: {
809
+ color: "#569cd6"
810
+ },
811
+ boolean: {
812
+ color: "#569cd6"
813
+ },
814
+ number: {
815
+ color: "#b5cea8"
816
+ },
817
+ constant: {
818
+ color: "#9cdcfe"
819
+ },
820
+ symbol: {
821
+ color: "#b5cea8"
822
+ },
823
+ inserted: {
824
+ color: "#b5cea8"
825
+ },
826
+ unit: {
827
+ color: "#b5cea8"
828
+ },
829
+ selector: {
830
+ color: "#d7ba7d"
831
+ },
832
+ "attr-name": {
833
+ color: "#9cdcfe"
834
+ },
835
+ string: {
836
+ color: "#ce9178"
837
+ },
838
+ char: {
839
+ color: "#ce9178"
840
+ },
841
+ builtin: {
842
+ color: "#ce9178"
843
+ },
844
+ deleted: {
845
+ color: "#ce9178"
846
+ },
847
+ ".language-css .token.string.url": {
848
+ textDecoration: "underline"
849
+ },
850
+ operator: {
851
+ color: "#d4d4d4"
852
+ },
853
+ entity: {
854
+ color: "#569cd6"
855
+ },
856
+ "operator.arrow": {
857
+ color: "#569CD6"
858
+ },
859
+ atrule: {
860
+ color: "#ce9178"
861
+ },
862
+ "atrule.rule": {
863
+ color: "#c586c0"
864
+ },
865
+ "atrule.url": {
866
+ color: "#9cdcfe"
867
+ },
868
+ "atrule.url.function": {
869
+ color: "#dcdcaa"
870
+ },
871
+ "atrule.url.punctuation": {
872
+ color: "#d4d4d4"
873
+ },
874
+ keyword: {
875
+ color: "#569CD6"
876
+ },
877
+ "keyword.module": {
878
+ color: "#c586c0"
879
+ },
880
+ "keyword.control-flow": {
881
+ color: "#c586c0"
882
+ },
883
+ function: {
884
+ color: "#dcdcaa"
885
+ },
886
+ "function.maybe-class-name": {
887
+ color: "#dcdcaa"
888
+ },
889
+ regex: {
890
+ color: "#d16969"
891
+ },
892
+ important: {
893
+ color: "#569cd6"
894
+ },
895
+ italic: {
896
+ fontStyle: "italic"
897
+ },
898
+ "class-name": {
899
+ color: "#4ec9b0"
900
+ },
901
+ "maybe-class-name": {
902
+ color: "#4ec9b0"
903
+ },
904
+ console: {
905
+ color: "#9cdcfe"
906
+ },
907
+ parameter: {
908
+ color: "#9cdcfe"
909
+ },
910
+ interpolation: {
911
+ color: "#9cdcfe"
912
+ },
913
+ "punctuation.interpolation-punctuation": {
914
+ color: "#569cd6"
915
+ },
916
+ variable: {
917
+ color: "#9cdcfe"
918
+ },
919
+ "imports.maybe-class-name": {
920
+ color: "#9cdcfe"
921
+ },
922
+ "exports.maybe-class-name": {
923
+ color: "#9cdcfe"
924
+ },
925
+ escape: {
926
+ color: "#d7ba7d"
927
+ },
928
+ "tag.punctuation": {
929
+ color: "#808080"
930
+ },
931
+ cdata: {
932
+ color: "#808080"
933
+ },
934
+ "attr-value": {
935
+ color: "#ce9178"
936
+ },
937
+ "attr-value.punctuation": {
938
+ color: "#ce9178"
939
+ },
940
+ "attr-value.punctuation.attr-equals": {
941
+ color: "#d4d4d4"
942
+ },
943
+ namespace: {
944
+ color: "#4ec9b0"
945
+ },
946
+ 'pre[class*="language-javascript"]': {
947
+ color: "#9cdcfe"
948
+ },
949
+ 'code[class*="language-javascript"]': {
950
+ color: "#9cdcfe"
951
+ },
952
+ 'pre[class*="language-jsx"]': {
953
+ color: "#9cdcfe"
954
+ },
955
+ 'code[class*="language-jsx"]': {
956
+ color: "#9cdcfe"
957
+ },
958
+ 'pre[class*="language-typescript"]': {
959
+ color: "#9cdcfe"
960
+ },
961
+ 'code[class*="language-typescript"]': {
962
+ color: "#9cdcfe"
963
+ },
964
+ 'pre[class*="language-tsx"]': {
965
+ color: "#9cdcfe"
966
+ },
967
+ 'code[class*="language-tsx"]': {
968
+ color: "#9cdcfe"
969
+ },
970
+ 'pre[class*="language-css"]': {
971
+ color: "#ce9178"
972
+ },
973
+ 'code[class*="language-css"]': {
974
+ color: "#ce9178"
975
+ },
976
+ 'pre[class*="language-html"]': {
977
+ color: "#d4d4d4"
978
+ },
979
+ 'code[class*="language-html"]': {
980
+ color: "#d4d4d4"
981
+ },
982
+ ".language-regex .token.anchor": {
983
+ color: "#dcdcaa"
984
+ },
985
+ ".language-html .token.punctuation": {
986
+ color: "#808080"
987
+ },
988
+ 'pre[class*="language-"] > code[class*="language-"]': {
989
+ position: "relative",
990
+ zIndex: "1"
991
+ },
992
+ ".line-highlight.line-highlight": {
993
+ background: "#f7ebc6",
994
+ boxShadow: "inset 5px 0 0 #f7d87c",
995
+ zIndex: "0"
996
+ }
997
+ }, ze = ({ url: r }) => {
998
+ const [t, n] = w(""), [i, c] = w(!0), [d, s] = w(null);
999
+ return M(() => {
1000
+ (async () => {
1001
+ try {
1002
+ c(!0), s(null);
1003
+ const a = await fetch(r);
1004
+ if (!a.ok)
1005
+ throw new Error("加载失败");
1006
+ const g = await a.text();
1007
+ n(g);
1008
+ } catch (a) {
1009
+ s("Markdown 文件加载失败"), console.error(a);
1010
+ } finally {
1011
+ c(!1);
1012
+ }
1013
+ })();
1014
+ }, [r]), i ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }) : d ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: d }) }) }) : /* @__PURE__ */ e("div", { className: "w-full h-full overflow-auto p-8", children: /* @__PURE__ */ e("div", { className: "max-w-4xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl p-8 border border-white/10", children: /* @__PURE__ */ e("div", { className: "prose prose-invert prose-lg max-w-none", children: /* @__PURE__ */ e(
1015
+ ge,
1016
+ {
1017
+ remarkPlugins: [be],
1018
+ components: {
1019
+ code({ node: o, inline: a, className: g, children: u, ...h }) {
1020
+ const v = /language-(\w+)/.exec(g || "");
1021
+ return !a && v ? /* @__PURE__ */ e(
1022
+ X,
1023
+ {
1024
+ style: q,
1025
+ language: v[1],
1026
+ PreTag: "div",
1027
+ className: "rounded-lg",
1028
+ ...h,
1029
+ children: String(u).replace(/\n$/, "")
1030
+ }
1031
+ ) : /* @__PURE__ */ e("code", { className: "bg-white/10 px-1.5 py-0.5 rounded text-sm", ...h, children: u });
1032
+ },
1033
+ h1: ({ children: o }) => /* @__PURE__ */ e("h1", { className: "text-4xl font-bold mb-4 text-white border-b border-white/20 pb-2", children: o }),
1034
+ h2: ({ children: o }) => /* @__PURE__ */ e("h2", { className: "text-3xl font-bold mb-3 text-white mt-8", children: o }),
1035
+ h3: ({ children: o }) => /* @__PURE__ */ e("h3", { className: "text-2xl font-bold mb-2 text-white mt-6", children: o }),
1036
+ p: ({ children: o }) => /* @__PURE__ */ e("p", { className: "text-white/90 mb-4 leading-relaxed", children: o }),
1037
+ a: ({ href: o, children: a }) => /* @__PURE__ */ e(
1038
+ "a",
1039
+ {
1040
+ href: o,
1041
+ className: "text-blue-400 hover:text-blue-300 underline",
1042
+ target: "_blank",
1043
+ rel: "noopener noreferrer",
1044
+ children: a
1045
+ }
1046
+ ),
1047
+ ul: ({ children: o }) => /* @__PURE__ */ e("ul", { className: "list-disc list-inside mb-4 text-white/90", children: o }),
1048
+ ol: ({ children: o }) => /* @__PURE__ */ e("ol", { className: "list-decimal list-inside mb-4 text-white/90", children: o }),
1049
+ li: ({ children: o }) => /* @__PURE__ */ e("li", { className: "mb-1", children: o }),
1050
+ blockquote: ({ children: o }) => /* @__PURE__ */ e("blockquote", { className: "border-l-4 border-blue-500 pl-4 italic text-white/80 my-4", children: o }),
1051
+ table: ({ children: o }) => /* @__PURE__ */ e("div", { className: "overflow-x-auto my-4", children: /* @__PURE__ */ e("table", { className: "min-w-full border border-white/20", children: o }) }),
1052
+ th: ({ children: o }) => /* @__PURE__ */ e("th", { className: "border border-white/20 px-4 py-2 bg-white/10 text-white font-semibold", children: o }),
1053
+ td: ({ children: o }) => /* @__PURE__ */ e("td", { className: "border border-white/20 px-4 py-2 text-white/90", children: o }),
1054
+ hr: () => /* @__PURE__ */ e("hr", { className: "border-white/20 my-6" }),
1055
+ img: ({ src: o, alt: a }) => /* @__PURE__ */ e("img", { src: o, alt: a, className: "rounded-lg max-w-full h-auto my-4" })
1056
+ },
1057
+ children: t
1058
+ }
1059
+ ) }) }) });
1060
+ }, Fe = (r) => {
1061
+ var i;
1062
+ const t = ((i = r.split(".").pop()) == null ? void 0 : i.toLowerCase()) || "";
1063
+ return {
1064
+ js: "javascript",
1065
+ jsx: "jsx",
1066
+ ts: "typescript",
1067
+ tsx: "tsx",
1068
+ py: "python",
1069
+ java: "java",
1070
+ cpp: "cpp",
1071
+ c: "c",
1072
+ cs: "csharp",
1073
+ php: "php",
1074
+ rb: "ruby",
1075
+ go: "go",
1076
+ rs: "rust",
1077
+ swift: "swift",
1078
+ kt: "kotlin",
1079
+ scala: "scala",
1080
+ sh: "bash",
1081
+ bash: "bash",
1082
+ zsh: "bash",
1083
+ json: "json",
1084
+ xml: "xml",
1085
+ html: "html",
1086
+ css: "css",
1087
+ scss: "scss",
1088
+ sass: "sass",
1089
+ less: "less",
1090
+ sql: "sql",
1091
+ yaml: "yaml",
1092
+ yml: "yaml",
1093
+ toml: "toml",
1094
+ ini: "ini",
1095
+ conf: "nginx",
1096
+ md: "markdown",
1097
+ txt: "text"
1098
+ }[t] || "text";
1099
+ }, We = ({ url: r, fileName: t }) => {
1100
+ const [n, i] = w(""), [c, d] = w(!0), [s, o] = w(null), a = Fe(t);
1101
+ return M(() => {
1102
+ (async () => {
1103
+ try {
1104
+ d(!0), o(null);
1105
+ const u = await fetch(r);
1106
+ if (!u.ok)
1107
+ throw new Error("加载失败");
1108
+ const h = await u.text();
1109
+ i(h);
1110
+ } catch (u) {
1111
+ o("文本文件加载失败"), console.error(u);
1112
+ } finally {
1113
+ d(!1);
1114
+ }
1115
+ })();
1116
+ }, [r]), c ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin" }) }) : s ? /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ e("div", { className: "text-white/70 text-center", children: /* @__PURE__ */ e("p", { className: "text-lg", children: s }) }) }) : /* @__PURE__ */ e("div", { className: "w-full h-full overflow-auto p-8", children: /* @__PURE__ */ p("div", { className: "max-w-6xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl border border-white/10 overflow-hidden", children: [
1117
+ /* @__PURE__ */ p("div", { className: "flex items-center gap-3 px-6 py-4 bg-white/5 border-b border-white/10", children: [
1118
+ /* @__PURE__ */ e(re, { className: "w-5 h-5 text-white/70" }),
1119
+ /* @__PURE__ */ e("span", { className: "text-white font-medium", children: t }),
1120
+ /* @__PURE__ */ e("span", { className: "ml-auto text-xs text-white/50 uppercase", children: a })
1121
+ ] }),
1122
+ /* @__PURE__ */ e("div", { className: "text-sm", children: a === "text" ? /* @__PURE__ */ e("pre", { className: "p-6 text-white/90 font-mono whitespace-pre-wrap break-words", children: n }) : /* @__PURE__ */ e(
1123
+ X,
1124
+ {
1125
+ language: a,
1126
+ style: q,
1127
+ showLineNumbers: !0,
1128
+ customStyle: {
1129
+ margin: 0,
1130
+ padding: "1.5rem",
1131
+ background: "transparent",
1132
+ fontSize: "0.875rem"
1133
+ },
1134
+ lineNumberStyle: {
1135
+ minWidth: "3em",
1136
+ paddingRight: "1em",
1137
+ color: "rgba(255, 255, 255, 0.3)",
1138
+ userSelect: "none"
1139
+ },
1140
+ children: n
1141
+ }
1142
+ ) })
1143
+ ] }) });
1144
+ }, $e = ({
1145
+ fileName: r,
1146
+ fileType: t,
1147
+ onDownload: n
1148
+ }) => /* @__PURE__ */ p("div", { className: "flex flex-col items-center justify-center w-full h-full p-8 gap-6", children: [
1149
+ /* @__PURE__ */ e("div", { className: "w-32 h-32 rounded-full bg-white/10 flex items-center justify-center", children: /* @__PURE__ */ e(oe, { className: "w-16 h-16 text-white/70" }) }),
1150
+ /* @__PURE__ */ p("div", { className: "text-white text-center", children: [
1151
+ /* @__PURE__ */ e("p", { className: "text-xl font-medium mb-2", children: r }),
1152
+ /* @__PURE__ */ p("p", { className: "text-white/70", children: [
1153
+ "不支持预览此文件类型 (",
1154
+ t,
1155
+ ")"
1156
+ ] })
1157
+ ] }),
1158
+ /* @__PURE__ */ p(
1159
+ "button",
1160
+ {
1161
+ onClick: n,
1162
+ 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",
1163
+ children: [
1164
+ /* @__PURE__ */ e(V, { className: "w-5 h-5" }),
1165
+ "下载文件查看"
1166
+ ]
1167
+ }
1168
+ )
1169
+ ] }), Be = (r) => {
1170
+ var c;
1171
+ const t = ((c = r.name.split(".").pop()) == null ? void 0 : c.toLowerCase()) || "", n = r.type.toLowerCase();
1172
+ if (n.startsWith("image/") || ["jpg", "jpeg", "png", "gif", "webp", "svg"].includes(t))
1173
+ return "image";
1174
+ if (n.includes("pdf") || t === "pdf")
1175
+ return "pdf";
1176
+ if (n.includes("wordprocessingml") || t === "docx")
1177
+ return "docx";
1178
+ if (n.includes("spreadsheetml") || t === "xlsx")
1179
+ return "xlsx";
1180
+ if (n.includes("presentationml") || t === "pptx" || t === "ppt")
1181
+ return "pptx";
1182
+ if (n.startsWith("video/") || ["mp4", "webm", "ogg", "ogv", "mov", "avi", "mkv", "m4v", "3gp", "flv"].includes(t))
1183
+ return "video";
1184
+ if (n.startsWith("audio/") || ["mp3", "wav", "ogg", "m4a", "flac", "aac"].includes(t))
1185
+ return "audio";
1186
+ if (t === "md" || t === "markdown")
1187
+ return "markdown";
1188
+ const i = [
1189
+ "txt",
1190
+ "log",
1191
+ "csv",
1192
+ "js",
1193
+ "jsx",
1194
+ "ts",
1195
+ "tsx",
1196
+ "json",
1197
+ "py",
1198
+ "java",
1199
+ "cpp",
1200
+ "c",
1201
+ "h",
1202
+ "cs",
1203
+ "php",
1204
+ "rb",
1205
+ "go",
1206
+ "rs",
1207
+ "swift",
1208
+ "kt",
1209
+ "html",
1210
+ "css",
1211
+ "scss",
1212
+ "sass",
1213
+ "less",
1214
+ "xml",
1215
+ "yaml",
1216
+ "yml",
1217
+ "toml",
1218
+ "ini",
1219
+ "conf",
1220
+ "sh",
1221
+ "bash",
1222
+ "zsh",
1223
+ "sql"
1224
+ ];
1225
+ return n.startsWith("text/") || i.includes(t) ? "text" : "unsupported";
1226
+ }, Ye = ({
1227
+ files: r,
1228
+ currentIndex: t,
1229
+ isOpen: n,
1230
+ onClose: i,
1231
+ onNavigate: c
1232
+ }) => {
1233
+ const [d, s] = w(1), [o, a] = w(0), [g, u] = w(1), [, h] = w(1), v = Z(() => Ne(r), [r]), l = v[t], m = l ? Be(l) : "unsupported";
1234
+ M(() => {
1235
+ s(1), a(0), u(1), h(1);
1236
+ }, [t]), M(() => {
1237
+ if (n) {
1238
+ const b = document.body.style.overflow, E = document.body.style.paddingRight, H = window.innerWidth - document.documentElement.clientWidth;
1239
+ return document.body.style.overflow = "hidden", H > 0 && (document.body.style.paddingRight = `${H}px`), () => {
1240
+ document.body.style.overflow = b, document.body.style.paddingRight = E;
1241
+ };
1242
+ }
1243
+ }, [n]), M(() => {
1244
+ if (!n) return;
1245
+ const b = (E) => {
1246
+ E.key === "Escape" ? i() : E.key === "ArrowLeft" && t > 0 ? c == null || c(t - 1) : E.key === "ArrowRight" && t < v.length - 1 && (c == null || c(t + 1));
1247
+ };
1248
+ return window.addEventListener("keydown", b), () => window.removeEventListener("keydown", b);
1249
+ }, [n, t, v.length, i, c]);
1250
+ const f = C(() => {
1251
+ s((b) => Math.min(b + 0.25, 5));
1252
+ }, []), y = C(() => {
1253
+ s((b) => Math.max(b - 0.25, 0.5));
1254
+ }, []), k = C(() => {
1255
+ a((b) => b + 90);
1256
+ }, []), T = C(() => {
1257
+ a((b) => b - 90);
1258
+ }, []), L = C(() => {
1259
+ s(1), a(0);
1260
+ }, []), P = C(() => {
1261
+ s(1);
1262
+ }, []), z = C((b) => {
1263
+ s(b);
1264
+ }, []), x = C(() => {
1265
+ s(1), a(0);
1266
+ }, []), j = C(() => {
1267
+ if (!l) return;
1268
+ const b = document.createElement("a");
1269
+ b.href = l.url, b.download = l.name, b.click();
1270
+ }, [l]);
1271
+ if (!n || !l) return null;
1272
+ const N = m === "image" || m === "pdf", R = m === "image";
1273
+ return /* @__PURE__ */ e(_, { children: n && /* @__PURE__ */ e(
1274
+ F.div,
1275
+ {
1276
+ initial: { opacity: 0 },
1277
+ animate: { opacity: 1 },
1278
+ exit: { opacity: 0 },
1279
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md overflow-hidden",
1280
+ onClick: i,
1281
+ onWheel: (b) => b.stopPropagation(),
1282
+ children: /* @__PURE__ */ p(
1283
+ "div",
1284
+ {
1285
+ className: "relative w-full h-full flex flex-col overflow-hidden",
1286
+ onClick: (b) => b.stopPropagation(),
1287
+ children: [
1288
+ /* @__PURE__ */ e(
1289
+ F.div,
1290
+ {
1291
+ initial: { y: -100 },
1292
+ animate: { y: 0 },
1293
+ exit: { y: -100 },
1294
+ className: "absolute top-0 left-0 right-0 z-10 p-4",
1295
+ children: /* @__PURE__ */ p("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: [
1296
+ /* @__PURE__ */ p("div", { className: "flex-1 min-w-0", children: [
1297
+ /* @__PURE__ */ e("h2", { className: "text-white font-medium text-lg truncate", children: l.name }),
1298
+ /* @__PURE__ */ p("p", { className: "text-white/60 text-sm", children: [
1299
+ t + 1,
1300
+ " / ",
1301
+ v.length
1302
+ ] })
1303
+ ] }),
1304
+ /* @__PURE__ */ p("div", { className: "flex items-center gap-2 ml-4", children: [
1305
+ N && /* @__PURE__ */ p($, { children: [
1306
+ /* @__PURE__ */ e(
1307
+ D,
1308
+ {
1309
+ icon: /* @__PURE__ */ e(ne, { className: "w-5 h-5" }),
1310
+ label: "缩小",
1311
+ onClick: y,
1312
+ disabled: d <= 0.5
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ p("span", { className: "text-white/70 text-sm min-w-[4rem] text-center font-medium", children: [
1316
+ Math.round(d * 100),
1317
+ "%"
1318
+ ] }),
1319
+ /* @__PURE__ */ e(
1320
+ D,
1321
+ {
1322
+ icon: /* @__PURE__ */ e(le, { className: "w-5 h-5" }),
1323
+ label: "放大",
1324
+ onClick: f,
1325
+ disabled: d >= 5
1326
+ }
1327
+ ),
1328
+ /* @__PURE__ */ e("div", { className: "w-px h-6 bg-white/20 mx-2" }),
1329
+ /* @__PURE__ */ e(
1330
+ D,
1331
+ {
1332
+ icon: /* @__PURE__ */ e(ae, { className: "w-5 h-5" }),
1333
+ label: "适应窗口",
1334
+ onClick: L
1335
+ }
1336
+ ),
1337
+ /* @__PURE__ */ e(
1338
+ D,
1339
+ {
1340
+ icon: /* @__PURE__ */ e(se, { className: "w-5 h-5" }),
1341
+ label: "原始尺寸",
1342
+ onClick: P
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ e("div", { className: "w-px h-6 bg-white/20 mx-2" })
1346
+ ] }),
1347
+ R && /* @__PURE__ */ p($, { children: [
1348
+ /* @__PURE__ */ e(
1349
+ D,
1350
+ {
1351
+ icon: /* @__PURE__ */ e(ie, { className: "w-5 h-5" }),
1352
+ label: "向左旋转",
1353
+ onClick: T
1354
+ }
1355
+ ),
1356
+ /* @__PURE__ */ e(
1357
+ D,
1358
+ {
1359
+ icon: /* @__PURE__ */ e(ce, { className: "w-5 h-5" }),
1360
+ label: "向右旋转",
1361
+ onClick: k
1362
+ }
1363
+ ),
1364
+ /* @__PURE__ */ e("div", { className: "w-px h-6 bg-white/20 mx-2" })
1365
+ ] }),
1366
+ (N || R) && /* @__PURE__ */ p($, { children: [
1367
+ /* @__PURE__ */ e(
1368
+ D,
1369
+ {
1370
+ icon: /* @__PURE__ */ e(de, { className: "w-5 h-5" }),
1371
+ label: "复原",
1372
+ onClick: x
1373
+ }
1374
+ ),
1375
+ /* @__PURE__ */ e("div", { className: "w-px h-6 bg-white/20 mx-2" })
1376
+ ] }),
1377
+ /* @__PURE__ */ e(
1378
+ D,
1379
+ {
1380
+ icon: /* @__PURE__ */ e(V, { className: "w-5 h-5" }),
1381
+ label: "下载",
1382
+ onClick: j
1383
+ }
1384
+ ),
1385
+ /* @__PURE__ */ e("div", { className: "w-px h-6 bg-white/20 mx-2" }),
1386
+ /* @__PURE__ */ e(
1387
+ D,
1388
+ {
1389
+ icon: /* @__PURE__ */ e(me, { className: "w-5 h-5" }),
1390
+ label: "关闭",
1391
+ onClick: i
1392
+ }
1393
+ )
1394
+ ] })
1395
+ ] })
1396
+ }
1397
+ ),
1398
+ /* @__PURE__ */ p("div", { className: "flex-1 flex items-center justify-center pt-24 pb-8 overflow-auto", children: [
1399
+ m === "image" && /* @__PURE__ */ e(
1400
+ ke,
1401
+ {
1402
+ url: l.url,
1403
+ zoom: d,
1404
+ rotation: o,
1405
+ onZoomChange: z
1406
+ }
1407
+ ),
1408
+ m === "pdf" && /* @__PURE__ */ e(
1409
+ Te,
1410
+ {
1411
+ url: l.url,
1412
+ zoom: d,
1413
+ currentPage: g,
1414
+ onPageChange: u,
1415
+ onTotalPagesChange: h
1416
+ }
1417
+ ),
1418
+ m === "docx" && /* @__PURE__ */ e(Le, { url: l.url }),
1419
+ m === "xlsx" && /* @__PURE__ */ e(Se, { url: l.url }),
1420
+ m === "pptx" && /* @__PURE__ */ e(Pe, { url: l.url }),
1421
+ m === "video" && /* @__PURE__ */ e(De, { url: l.url }),
1422
+ m === "audio" && /* @__PURE__ */ e(Ee, { url: l.url, fileName: l.name }),
1423
+ m === "markdown" && /* @__PURE__ */ e(ze, { url: l.url }),
1424
+ m === "text" && /* @__PURE__ */ e(We, { url: l.url, fileName: l.name }),
1425
+ m === "unsupported" && /* @__PURE__ */ e(
1426
+ $e,
1427
+ {
1428
+ fileName: l.name,
1429
+ fileType: l.type,
1430
+ onDownload: j
1431
+ }
1432
+ )
1433
+ ] }),
1434
+ v.length > 1 && /* @__PURE__ */ p($, { children: [
1435
+ t > 0 && /* @__PURE__ */ e(
1436
+ F.button,
1437
+ {
1438
+ initial: { x: -100, opacity: 0 },
1439
+ animate: { x: 0, opacity: 1 },
1440
+ exit: { x: -100, opacity: 0 },
1441
+ onClick: () => c == null ? void 0 : c(t - 1),
1442
+ 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",
1443
+ children: /* @__PURE__ */ e(ue, { className: "w-6 h-6" })
1444
+ }
1445
+ ),
1446
+ t < v.length - 1 && /* @__PURE__ */ e(
1447
+ F.button,
1448
+ {
1449
+ initial: { x: 100, opacity: 0 },
1450
+ animate: { x: 0, opacity: 1 },
1451
+ exit: { x: 100, opacity: 0 },
1452
+ onClick: () => c == null ? void 0 : c(t + 1),
1453
+ 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",
1454
+ children: /* @__PURE__ */ e(he, { className: "w-6 h-6" })
1455
+ }
1456
+ )
1457
+ ] })
1458
+ ]
1459
+ }
1460
+ )
1461
+ }
1462
+ ) });
1463
+ }, D = ({ icon: r, label: t, onClick: n, disabled: i }) => /* @__PURE__ */ e(
1464
+ "button",
1465
+ {
1466
+ onClick: n,
1467
+ disabled: i,
1468
+ title: t,
1469
+ className: `p-2 rounded-lg transition-all ${i ? "text-white/30 cursor-not-allowed" : "text-white hover:bg-white/10 active:bg-white/20"}`,
1470
+ children: r
1471
+ }
1472
+ );
1473
+ export {
1474
+ Ye as FilePreviewModal,
1475
+ ye as normalizeFile,
1476
+ Ne as normalizeFiles
1477
+ };
1478
+ //# sourceMappingURL=index.mjs.map