@eternalheart/react-file-preview 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils/fileNormalizer.ts","../src/renderers/ImageRenderer.tsx","../src/utils/pdfConfig.ts","../src/renderers/PdfRenderer.tsx","../src/renderers/DocxRenderer.tsx","../src/renderers/XlsxRenderer.tsx","../src/renderers/PptxRenderer.tsx","../src/renderers/VideoRenderer.tsx","../src/renderers/AudioRenderer.tsx","../../../node_modules/.pnpm/react-syntax-highlighter@16.1.0_react@18.3.1/node_modules/react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js","../src/renderers/MarkdownRenderer.tsx","../src/renderers/TextRenderer.tsx","../src/renderers/UnsupportedRenderer.tsx","../src/FilePreviewModal.tsx","../src/index.ts"],"sourcesContent":["import { PreviewFile, PreviewFileInput } from '../types';\n\n/**\n * 从 URL 字符串中提取文件名\n */\nfunction getFileNameFromUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const fileName = pathname.split('/').pop() || 'file';\n return decodeURIComponent(fileName);\n } catch {\n // 如果不是有效的 URL,尝试从路径中提取\n const fileName = url.split('/').pop() || 'file';\n return decodeURIComponent(fileName);\n }\n}\n\n/**\n * 从文件名中推断 MIME 类型\n */\nfunction inferMimeType(fileName: string): string {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n \n const mimeTypes: Record<string, string> = {\n // 图片\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n \n // 视频\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/x-m4v',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n \n // 音频\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n m4a: 'audio/mp4',\n aac: 'audio/aac',\n flac: 'audio/flac',\n \n // 文档\n pdf: 'application/pdf',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n ppt: 'application/vnd.ms-powerpoint',\n \n // 文本\n txt: 'text/plain',\n md: 'text/markdown',\n markdown: 'text/markdown',\n json: 'application/json',\n xml: 'application/xml',\n html: 'text/html',\n css: 'text/css',\n js: 'text/javascript',\n ts: 'text/typescript',\n jsx: 'text/javascript',\n tsx: 'text/typescript',\n py: 'text/x-python',\n java: 'text/x-java',\n cpp: 'text/x-c++src',\n c: 'text/x-csrc',\n cs: 'text/x-csharp',\n php: 'text/x-php',\n rb: 'text/x-ruby',\n go: 'text/x-go',\n rs: 'text/x-rust',\n yaml: 'text/yaml',\n yml: 'text/yaml',\n };\n \n return mimeTypes[ext] || 'application/octet-stream';\n}\n\n/**\n * 标准化文件输入为 PreviewFile 格式\n * 支持三种输入类型:\n * 1. File 对象(原生浏览器 File)\n * 2. PreviewFileLink 对象(包含 name, url, type 等属性)\n * 3. string(HTTP URL)\n */\nexport function normalizeFile(input: PreviewFileInput, index: number = 0): PreviewFile {\n // 情况 1: 原生 File 对象\n if (input instanceof File) {\n return {\n id: `file-${Date.now()}-${index}`,\n name: input.name,\n url: URL.createObjectURL(input),\n type: input.type || inferMimeType(input.name),\n size: input.size,\n };\n }\n \n // 情况 2: 字符串 URL\n if (typeof input === 'string') {\n const fileName = getFileNameFromUrl(input);\n return {\n id: `url-${Date.now()}-${index}`,\n name: fileName,\n url: input,\n type: inferMimeType(fileName),\n };\n }\n \n // 情况 3: PreviewFileLink 对象\n return {\n id: input.id || `link-${Date.now()}-${index}`,\n name: input.name,\n url: input.url,\n type: input.type || inferMimeType(input.name),\n size: input.size,\n };\n}\n\n/**\n * 批量标准化文件输入\n */\nexport function normalizeFiles(inputs: PreviewFileInput[]): PreviewFile[] {\n return inputs.map((input, index) => normalizeFile(input, index));\n}\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { motion } from 'framer-motion';\n\ninterface ImageRendererProps {\n url: string;\n zoom: number;\n rotation: number;\n onZoomChange?: (zoom: number) => void;\n}\n\nexport const ImageRenderer: React.FC<ImageRendererProps> = ({\n url,\n zoom,\n rotation,\n onZoomChange\n}) => {\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [position, setPosition] = useState({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [internalZoom, setInternalZoom] = useState(1); // 内部缩放状态\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setLoaded(false);\n setError(null);\n setPosition({ x: 0, y: 0 });\n setInternalZoom(1);\n }, [url]);\n\n // 当外部 zoom 改变时,同步内部 zoom\n useEffect(() => {\n setInternalZoom(zoom);\n }, [zoom]);\n\n // 重置位置当缩放或旋转改变时\n useEffect(() => {\n setPosition({ x: 0, y: 0 });\n }, [zoom, rotation]);\n\n const handleLoad = () => {\n setLoaded(true);\n };\n\n const handleError = () => {\n setError('图片加载失败');\n setLoaded(true);\n };\n\n const handleDoubleClick = () => {\n // 双击重置位置\n setPosition({ x: 0, y: 0 });\n };\n\n // 鼠标滚轮缩放\n const handleWheel = useCallback((e: React.WheelEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const delta = e.deltaY > 0 ? -0.1 : 0.1;\n setInternalZoom(prev => {\n const newZoom = Math.max(0.5, Math.min(5, prev + delta)); // 限制缩放范围 0.5-5\n // 同步缩放比例到父组件\n if (onZoomChange) {\n onZoomChange(newZoom);\n }\n return newZoom;\n });\n }, [onZoomChange]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (e.button !== 0) return; // 只响应左键\n setIsDragging(true);\n setDragStart({\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n });\n }, [position]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!isDragging) return;\n setPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n });\n }, [isDragging, dragStart]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"flex items-center justify-center w-full h-full overflow-hidden\"\n onWheel={handleWheel}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n style={{ cursor: isDragging ? 'grabbing' : 'grab' }}\n >\n {!loaded && !error && (\n <div className=\"flex items-center justify-center\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n )}\n\n {error && (\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n )}\n\n <motion.img\n src={url}\n alt=\"Preview\"\n className={`max-w-none select-none ${!loaded ? 'hidden' : ''}`}\n style={{\n transform: `translate(${position.x}px, ${position.y}px) scale(${internalZoom}) rotate(${rotation}deg)`,\n transformOrigin: 'center',\n transition: isDragging ? 'none' : 'transform 0.3s ease-out',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onDoubleClick={handleDoubleClick}\n initial={{ opacity: 0 }}\n animate={{ opacity: loaded ? 1 : 0 }}\n transition={{ duration: 0.3 }}\n draggable={false}\n />\n </div>\n );\n};\n\n","import { pdfjs } from 'react-pdf';\n\n/**\n * PDF.js Worker 配置选项\n */\nexport interface PdfConfigOptions {\n /**\n * PDF.js worker 文件路径\n * 默认使用 CDN: `https://unpkg.com/pdfjs-dist@${version}/build/pdf.worker.min.mjs`\n */\n workerSrc?: string;\n \n /**\n * CMap 文件目录路径\n * 默认使用 CDN: `https://unpkg.com/pdfjs-dist@${version}/cmaps/`\n */\n cMapUrl?: string;\n \n /**\n * 是否使用压缩的 CMap 文件\n * 默认: true\n */\n cMapPacked?: boolean;\n}\n\n/**\n * 配置 PDF.js\n *\n * @example\n * ```ts\n * // 使用本地静态文件(推荐用于生产环境)\n * configurePdfjs({\n * workerSrc: '/pdfjs/pdf.worker.min.mjs',\n * cMapUrl: '/pdfjs/cmaps/',\n * cMapPacked: true\n * });\n * ```\n *\n * @example\n * ```ts\n * // 使用 CDN(默认配置)\n * configurePdfjs(); // 自动使用 unpkg CDN\n * ```\n */\nexport function configurePdfjs(options?: PdfConfigOptions) {\n if (typeof window === 'undefined') return;\n\n const {\n workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`,\n cMapUrl = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n cMapPacked = true\n } = options || {};\n\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n // @ts-ignore - cMapUrl 和 cMapPacked 在 react-pdf 的类型定义中不存在,但在运行时可用\n pdfjs.GlobalWorkerOptions.cMapUrl = cMapUrl;\n // @ts-ignore\n pdfjs.GlobalWorkerOptions.cMapPacked = cMapPacked;\n}\n\n// 默认使用 CDN 配置\nconfigurePdfjs();\n\nexport { pdfjs };\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { Document, Page } from 'react-pdf';\nimport 'react-pdf/dist/esm/Page/AnnotationLayer.css';\nimport 'react-pdf/dist/esm/Page/TextLayer.css';\n\n// 导入 PDF.js 配置\nimport '../utils/pdfConfig';\n\ninterface PdfRendererProps {\n url: string;\n zoom: number;\n currentPage: number;\n onPageChange: (page: number) => void;\n onTotalPagesChange: (total: number) => void;\n}\n\nexport const PdfRenderer: React.FC<PdfRendererProps> = ({\n url,\n zoom,\n currentPage,\n onPageChange,\n onTotalPagesChange,\n}) => {\n const [numPages, setNumPages] = useState<number>(0);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const pageRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n useEffect(() => {\n setError(null);\n }, [url]);\n\n const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {\n setNumPages(numPages);\n onTotalPagesChange(numPages);\n onPageChange(1);\n };\n\n const onDocumentLoadError = (error: Error) => {\n console.error('PDF 加载错误:', error);\n setError('PDF 文件加载失败');\n };\n\n // 滚动时更新当前页码\n const handleScroll = useCallback(() => {\n if (!containerRef.current) return;\n\n const container = containerRef.current;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n // 找到当前可见的页面\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageRefs.current.forEach((pageElement, pageNumber) => {\n const rect = pageElement.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const pageCenter = rect.top - containerRect.top + rect.height / 2 + scrollTop;\n const distance = Math.abs(pageCenter - scrollCenter);\n\n if (distance < minDistance) {\n minDistance = distance;\n currentVisiblePage = pageNumber;\n }\n });\n\n if (currentVisiblePage !== currentPage) {\n onPageChange(currentVisiblePage);\n }\n }, [currentPage, onPageChange]);\n\n // 监听滚动事件\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [handleScroll]);\n\n // 设置页面引用\n const setPageRef = useCallback((pageNumber: number, element: HTMLDivElement | null) => {\n if (element) {\n pageRefs.current.set(pageNumber, element);\n } else {\n pageRefs.current.delete(pageNumber);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col items-center w-full h-full overflow-auto py-8 px-4\"\n >\n {error && (\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n )}\n\n {!error && (\n <Document\n file={url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onDocumentLoadError}\n loading={\n <div className=\"flex items-center justify-center min-h-screen\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {Array.from(new Array(numPages), (_, index) => {\n const pageNumber = index + 1;\n return (\n <div\n key={`page_${pageNumber}`}\n ref={(el) => setPageRef(pageNumber, el)}\n className=\"relative\"\n >\n <Page\n pageNumber={pageNumber}\n scale={zoom}\n loading={\n <div className=\"flex items-center justify-center p-8 bg-white/5 rounded-lg min-h-[600px]\">\n <div className=\"w-8 h-8 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n }\n renderTextLayer={true}\n renderAnnotationLayer={true}\n className=\"shadow-2xl\"\n />\n {/* 页码标签 */}\n <div className=\"absolute top-2 right-2 bg-black/60 backdrop-blur-sm text-white text-xs px-3 py-1 rounded-full\">\n {pageNumber}\n </div>\n </div>\n );\n })}\n </div>\n </Document>\n )}\n\n {/* 底部页码指示器 */}\n {numPages > 0 && (\n <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\">\n 第 {currentPage} 页 / 共 {numPages} 页\n </div>\n )}\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport mammoth from 'mammoth';\n\ninterface DocxRendererProps {\n url: string;\n}\n\nexport const DocxRenderer: React.FC<DocxRendererProps> = ({ url }) => {\n const [html, setHtml] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadDocx = async () => {\n setLoading(true);\n setError(null);\n setHtml('');\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const result = await mammoth.convertToHtml({ arrayBuffer });\n setHtml(result.value);\n } catch (err) {\n console.error('Docx 解析错误:', err);\n setError('Word 文档解析失败');\n } finally {\n setLoading(false);\n }\n };\n\n loadDocx();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-8\">\n <div\n className=\"max-w-4xl mx-auto bg-white rounded-lg shadow-2xl p-12\"\n dangerouslySetInnerHTML={{ __html: html }}\n style={{\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.6',\n color: '#333',\n }}\n />\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport * as XLSX from 'xlsx';\n\ninterface XlsxRendererProps {\n url: string;\n}\n\nexport const XlsxRenderer: React.FC<XlsxRendererProps> = ({ url }) => {\n const [sheets, setSheets] = useState<{ name: string; data: unknown[] }[]>([]);\n const [activeSheet, setActiveSheet] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadXlsx = async () => {\n setLoading(true);\n setError(null);\n setSheets([]);\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const workbook = XLSX.read(arrayBuffer, { type: 'array' });\n\n const parsedSheets = workbook.SheetNames.map((name) => {\n const worksheet = workbook.Sheets[name];\n const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 });\n return { name, data };\n });\n\n setSheets(parsedSheets);\n setActiveSheet(0);\n } catch (err) {\n console.error('Excel 解析错误:', err);\n setError('Excel 文件解析失败');\n } finally {\n setLoading(false);\n }\n };\n\n loadXlsx();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n const currentSheet = sheets[activeSheet];\n\n return (\n <div className=\"w-full h-full flex flex-col overflow-hidden\">\n {/* Sheet Tabs */}\n {sheets.length > 1 && (\n <div className=\"flex gap-2 p-4 bg-black/20 backdrop-blur-sm overflow-x-auto border-b border-white/10\">\n {sheets.map((sheet, index) => (\n <button\n key={index}\n onClick={() => setActiveSheet(index)}\n className={`px-4 py-2 rounded-lg text-sm font-medium transition-all ${activeSheet === index\n ? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-lg'\n : 'bg-white/10 text-white hover:bg-white/20'\n }`}\n >\n {sheet.name}\n </button>\n ))}\n </div>\n )}\n\n {/* Table */}\n <div className=\"flex-1 overflow-auto p-8\">\n <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\">\n <table className=\"min-w-full divide-y divide-white/10\">\n <tbody className=\"divide-y divide-white/10\">\n {currentSheet?.data.map((row, rowIndex) => (\n <tr\n key={rowIndex}\n className={`transition-colors ${rowIndex === 0\n ? 'bg-gradient-to-r from-purple-500/20 to-pink-500/20 font-semibold'\n : 'hover:bg-white/5'\n }`}\n >\n {(row as unknown[]).map((cell, cellIndex) => (\n <td\n key={cellIndex}\n className=\"px-6 py-4 whitespace-nowrap text-sm text-gray-200 border-r border-white/10\"\n >\n {String(cell ?? '')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n );\n};\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { Presentation } from 'lucide-react';\nimport { init } from 'pptx-preview';\n\ninterface PptxRendererProps {\n url: string;\n}\n\nexport const PptxRenderer: React.FC<PptxRendererProps> = ({ url }) => {\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const previewerRef = useRef<ReturnType<typeof init> | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const arrayBufferRef = useRef<ArrayBuffer | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n // 计算容器尺寸\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 960, height: 540 };\n\n const containerWidth = containerRef.current.clientWidth;\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n\n console.log('计算尺寸:', { width: containerWidth, height });\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current) return;\n\n console.log('重新初始化预览器...');\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch (e) {\n console.error('销毁预览器失败:', e);\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n console.log('重新初始化使用尺寸:', currentDimensions);\n\n // 初始化新的预览器\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: currentDimensions.height,\n });\n\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n console.log('重新初始化成功');\n } catch (e) {\n console.error('重新初始化失败:', e);\n }\n }, [calculateDimensions]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n // 跳过初始渲染时的尺寸检查\n if (isInitialRender) {\n isInitialRender = false;\n const initialDimensions = calculateDimensions();\n lastDimensionsRef.current = initialDimensions;\n return;\n }\n\n const newDimensions = calculateDimensions();\n\n // 检查尺寸是否真正变化(至少变化10px才触发)\n const lastDimensions = lastDimensionsRef.current;\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) {\n console.log('尺寸变化太小,忽略');\n return; // 尺寸变化太小,不做任何操作\n }\n\n console.log('检测到尺寸变化:', {\n old: lastDimensions,\n new: newDimensions,\n diff: { width: widthDiff, height: heightDiff }\n });\n\n // 更新最后的尺寸\n lastDimensionsRef.current = newDimensions;\n\n // 清除之前的定时器\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // 防抖:800ms 后重新初始化预览器\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (previewerRef.current && arrayBufferRef.current) {\n console.log('尺寸变化,准备重新初始化');\n reinitializePreviewer();\n }\n }, 800);\n };\n\n // 创建 ResizeObserver\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n // 开始观察容器\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, reinitializePreviewer]);\n\n useEffect(() => {\n let isMounted = true;\n\n const loadPptx = async () => {\n if (!containerRef.current) {\n console.log('Container ref not ready');\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n console.log('开始加载 PPTX:', url);\n\n // 获取文件\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n arrayBufferRef.current = arrayBuffer; // 保存到 ref\n console.log('文件加载成功,大小:', arrayBuffer.byteLength);\n\n if (!isMounted) return;\n\n // 清空容器\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n console.log('使用尺寸:', currentDimensions);\n\n // 初始化 pptx 预览器\n console.log('初始化预览器...');\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: currentDimensions.height,\n });\n\n previewerRef.current = previewer;\n\n // 预览 PPTX\n console.log('开始预览...');\n previewer.preview(arrayBuffer)\n .then(() => {\n console.log('预览成功');\n if (isMounted) {\n setLoading(false);\n }\n })\n .catch((previewErr) => {\n console.error('预览失败:', previewErr);\n if (isMounted) {\n setError('PPT 文件预览失败');\n setLoading(false);\n }\n });\n } catch (err) {\n console.error('PPTX 解析错误:', err);\n if (isMounted) {\n setError(err instanceof Error ? err.message : 'PPT 文件解析失败');\n setLoading(false);\n }\n }\n };\n\n // 延迟执行以确保 DOM 已准备好\n const timer = setTimeout(() => {\n loadPptx();\n }, 100);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n arrayBufferRef.current = null;\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch (e) {\n console.error('销毁预览器失败:', e);\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions]);\n\n return (\n <div className=\"relative flex flex-col items-center w-full h-full pt-[8px]\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl\">\n <div className=\"text-center\">\n <div className=\"w-12 h-12 mx-auto mb-3 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n <p className=\"text-sm text-white/70 font-medium\">加载 PPT 中...</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-2xl\">\n <div className=\"text-center max-w-md\">\n <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\">\n <Presentation className=\"w-16 h-16 text-white\" />\n </div>\n <p className=\"text-xl text-white/90 mb-3 font-medium\">PPT 预览</p>\n <p className=\"text-sm text-white/60 mb-6\">\n {error || '浏览器暂不支持直接预览 PPT 文件'}\n </p>\n <a\n href={url}\n download\n 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\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n 下载文件\n </a>\n <p className=\"text-xs text-white/40 mt-4\">\n 提示:可以使用 Microsoft PowerPoint 或 WPS 打开\n </p>\n </div>\n </div>\n )}\n\n {/* PPT 容器 - 始终渲染 */}\n <div\n ref={containerRef}\n className=\"pptx-wrapper w-full max-w-6xl\"\n />\n </div>\n );\n};\n\n","import { useRef, useEffect, useState } from 'react';\nimport videojs from 'video.js';\nimport 'video.js/dist/video-js.css';\n\ntype VideoJsPlayer = ReturnType<typeof videojs>;\n\ninterface VideoRendererProps {\n url: string;\n}\n\n// 根据 URL 获取视频 MIME 类型\nconst getVideoType = (url: string): string => {\n const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';\n const typeMap: Record<string, string> = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime', // MOV 使用 QuickTime MIME 类型\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/mp4',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n };\n return typeMap[ext] || 'video/mp4';\n};\n\nexport const VideoRenderer: React.FC<VideoRendererProps> = ({ url }) => {\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const videoRef = useRef<HTMLDivElement>(null);\n const playerRef = useRef<VideoJsPlayer | null>(null);\n\n useEffect(() => {\n // 确保 Video.js 播放器只初始化一次\n if (!playerRef.current && videoRef.current) {\n const videoElement = document.createElement('video-js');\n videoElement.classList.add('vjs-big-play-centered', 'vjs-theme-apple');\n videoRef.current.appendChild(videoElement);\n\n const videoType = getVideoType(url);\n\n // 为 MOV 格式提供多个 MIME 类型作为备用\n const sources = videoType === 'video/quicktime'\n ? [\n { src: url, type: 'video/quicktime' },\n { src: url, type: 'video/mp4' } // 备用方案\n ]\n : [{ src: url, type: videoType }];\n\n const player = videojs(videoElement, {\n controls: true,\n responsive: true,\n fluid: true,\n preload: 'auto',\n controlBar: {\n children: [\n 'playToggle',\n 'volumePanel',\n 'currentTimeDisplay',\n 'timeDivider',\n 'durationDisplay',\n 'progressControl',\n 'remainingTimeDisplay',\n 'fullscreenToggle'\n ],\n volumePanel: {\n inline: false\n }\n },\n html5: {\n vhs: {\n overrideNative: true\n },\n nativeVideoTracks: false,\n nativeAudioTracks: false,\n nativeTextTracks: false\n },\n sources\n });\n\n // 监听加载完成\n player.on('loadeddata', () => {\n setIsLoading(false);\n });\n\n player.on('error', () => {\n const error = player.error();\n console.error('Video.js error:', error);\n setError(`视频加载失败: ${error?.message || '未知错误'}`);\n setIsLoading(false);\n });\n\n playerRef.current = player;\n }\n }, [url]);\n\n // 清理函数\n useEffect(() => {\n const player = playerRef.current;\n\n return () => {\n if (player && !player.isDisposed()) {\n player.dispose();\n playerRef.current = null;\n }\n };\n }, []);\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-center\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-red-500/10 flex items-center justify-center\">\n <svg className=\"w-8 h-8 text-red-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </div>\n <p className=\"text-lg font-medium text-white/90 mb-2\">视频加载失败</p>\n <p className=\"text-sm text-white/60\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center justify-center w-full h-full p-8\">\n <div className=\"w-full max-w-5xl relative\">\n {/* 加载状态 */}\n {isLoading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded-2xl z-10\">\n <div className=\"text-center\">\n <div className=\"w-12 h-12 mx-auto mb-3 border-3 border-white/20 border-t-white rounded-full animate-spin\" />\n <p className=\"text-sm text-white/70 font-medium\">加载视频中...</p>\n </div>\n </div>\n )}\n\n {/* 视频播放器容器 */}\n <div\n ref={videoRef}\n className=\"overflow-hidden\"\n style={{\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)'\n }}\n />\n </div>\n </div>\n );\n};\n\n","import { useState, useRef, useEffect } from 'react';\nimport { Music, Play, Pause, Volume2, VolumeX, SkipBack, SkipForward } from 'lucide-react';\n\ninterface AudioRendererProps {\n url: string;\n fileName: string;\n}\n\nexport const AudioRenderer: React.FC<AudioRendererProps> = ({ url, fileName }) => {\n const [error, setError] = useState<string | null>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [volume, setVolume] = useState(1);\n const [isMuted, setIsMuted] = useState(false);\n const audioRef = useRef<HTMLAudioElement>(null);\n\n useEffect(() => {\n const audio = audioRef.current;\n if (!audio) return;\n\n const updateTime = () => {\n if (!isNaN(audio.currentTime)) {\n setCurrentTime(audio.currentTime);\n }\n };\n\n const updateDuration = () => {\n if (!isNaN(audio.duration) && isFinite(audio.duration)) {\n setDuration(audio.duration);\n }\n };\n\n const handleEnded = () => setIsPlaying(false);\n const handleCanPlay = () => updateDuration();\n\n audio.addEventListener('timeupdate', updateTime);\n audio.addEventListener('loadedmetadata', updateDuration);\n audio.addEventListener('durationchange', updateDuration);\n audio.addEventListener('canplay', handleCanPlay);\n audio.addEventListener('ended', handleEnded);\n\n // 立即尝试获取时长\n if (audio.readyState >= 1) {\n updateDuration();\n }\n\n return () => {\n audio.removeEventListener('timeupdate', updateTime);\n audio.removeEventListener('loadedmetadata', updateDuration);\n audio.removeEventListener('durationchange', updateDuration);\n audio.removeEventListener('canplay', handleCanPlay);\n audio.removeEventListener('ended', handleEnded);\n };\n }, []);\n\n const togglePlay = () => {\n if (audioRef.current) {\n if (isPlaying) {\n audioRef.current.pause();\n } else {\n audioRef.current.play();\n }\n setIsPlaying(!isPlaying);\n }\n };\n\n const handleSeek = (e: React.ChangeEvent<HTMLInputElement>) => {\n const time = parseFloat(e.target.value);\n setCurrentTime(time);\n if (audioRef.current) {\n audioRef.current.currentTime = time;\n }\n };\n\n const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const vol = parseFloat(e.target.value);\n setVolume(vol);\n if (audioRef.current) {\n audioRef.current.volume = vol;\n }\n if (vol > 0) setIsMuted(false);\n };\n\n const toggleMute = () => {\n if (audioRef.current) {\n audioRef.current.muted = !isMuted;\n setIsMuted(!isMuted);\n }\n };\n\n const skip = (seconds: number) => {\n if (audioRef.current) {\n audioRef.current.currentTime += seconds;\n }\n };\n\n const formatTime = (time: number) => {\n if (!isFinite(time) || isNaN(time) || time < 0) return '0:00';\n const minutes = Math.floor(time / 60);\n const seconds = Math.floor(time % 60);\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n };\n\n const handleError = () => {\n setError('音频加载失败');\n };\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-8 gap-8\">\n {/* 音频封面 */}\n <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\">\n <Music className=\"w-32 h-32 text-white\" />\n </div>\n\n {/* 文件名 */}\n <div className=\"text-white text-center max-w-md\">\n <p className=\"text-2xl font-medium mb-1\">{fileName}</p>\n <p className=\"text-sm text-white/60\">音频文件</p>\n </div>\n\n {/* 播放控制器 */}\n <div className=\"w-full max-w-md bg-white/10 backdrop-blur-xl rounded-2xl p-6 border border-white/20\">\n {/* 进度条 */}\n <div className=\"mb-4\">\n <div className=\"relative h-4 flex items-center\">\n {/* 进度条背景轨道 */}\n <div className=\"absolute w-full h-[6px] bg-white/20 rounded-full\" />\n {/* 已播放进度覆盖层 */}\n <div\n 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\"\n style={{\n width: `${duration > 0 ? (currentTime / duration) * 100 : (currentTime > 100 ? 100 : currentTime)}%`\n }}\n />\n {/* 进度条滑块 */}\n <input\n type=\"range\"\n min=\"0\"\n max={duration > 0 ? duration : 100 + (currentTime > 100 ? currentTime % 100 : 0)}\n value={currentTime}\n onChange={handleSeek}\n className=\"audio-slider absolute w-full\"\n />\n </div>\n <div className=\"flex justify-between text-xs text-white/60 mt-3\">\n <span>{formatTime(currentTime)}</span>\n <span>{formatTime(duration)}</span>\n </div>\n </div>\n\n {/* 控制按钮 */}\n <div className=\"flex items-center justify-center gap-4 mb-4\">\n <button\n onClick={() => skip(-10)}\n className=\"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all\"\n >\n <SkipBack className=\"w-5 h-5\" />\n </button>\n\n <button\n onClick={togglePlay}\n 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\"\n >\n {isPlaying ? <Pause className=\"w-6 h-6\" /> : <Play className=\"w-6 h-6 ml-1\" />}\n </button>\n\n <button\n onClick={() => skip(10)}\n className=\"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all\"\n >\n <SkipForward className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* 音量控制 */}\n <div className=\"flex items-center gap-3\">\n <button\n onClick={toggleMute}\n className=\"text-white/80 hover:text-white transition-colors\"\n >\n {isMuted || volume === 0 ? <VolumeX className=\"w-5 h-5\" /> : <Volume2 className=\"w-5 h-5\" />}\n </button>\n <div className=\"flex-1 relative h-3 flex items-center\">\n {/* 音量条背景轨道 */}\n <div className=\"absolute w-full h-[4px] bg-white/20 rounded-full\" />\n {/* 音量覆盖层 */}\n <div\n className=\"absolute h-[4px] bg-purple-500 rounded-full transition-all duration-100 pointer-events-none\"\n style={{\n width: `${(isMuted ? 0 : volume) * 100}%`\n }}\n />\n {/* 音量滑块 */}\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n value={isMuted ? 0 : volume}\n onChange={handleVolumeChange}\n className=\"volume-slider absolute w-full\"\n />\n </div>\n </div>\n </div>\n\n {/* 隐藏的 audio 元素 */}\n <audio\n ref={audioRef}\n src={url}\n onError={handleError}\n className=\"hidden\"\n />\n </div>\n );\n};\n\n","export default {\n \"pre[class*=\\\"language-\\\"]\": {\n \"color\": \"#d4d4d4\",\n \"fontSize\": \"13px\",\n \"textShadow\": \"none\",\n \"fontFamily\": \"Menlo, Monaco, Consolas, \\\"Andale Mono\\\", \\\"Ubuntu Mono\\\", \\\"Courier New\\\", monospace\",\n \"direction\": \"ltr\",\n \"textAlign\": \"left\",\n \"whiteSpace\": \"pre\",\n \"wordSpacing\": \"normal\",\n \"wordBreak\": \"normal\",\n \"lineHeight\": \"1.5\",\n \"MozTabSize\": \"4\",\n \"OTabSize\": \"4\",\n \"tabSize\": \"4\",\n \"WebkitHyphens\": \"none\",\n \"MozHyphens\": \"none\",\n \"msHyphens\": \"none\",\n \"hyphens\": \"none\",\n \"padding\": \"1em\",\n \"margin\": \".5em 0\",\n \"overflow\": \"auto\",\n \"background\": \"#1e1e1e\"\n },\n \"code[class*=\\\"language-\\\"]\": {\n \"color\": \"#d4d4d4\",\n \"fontSize\": \"13px\",\n \"textShadow\": \"none\",\n \"fontFamily\": \"Menlo, Monaco, Consolas, \\\"Andale Mono\\\", \\\"Ubuntu Mono\\\", \\\"Courier New\\\", monospace\",\n \"direction\": \"ltr\",\n \"textAlign\": \"left\",\n \"whiteSpace\": \"pre\",\n \"wordSpacing\": \"normal\",\n \"wordBreak\": \"normal\",\n \"lineHeight\": \"1.5\",\n \"MozTabSize\": \"4\",\n \"OTabSize\": \"4\",\n \"tabSize\": \"4\",\n \"WebkitHyphens\": \"none\",\n \"MozHyphens\": \"none\",\n \"msHyphens\": \"none\",\n \"hyphens\": \"none\"\n },\n \"pre[class*=\\\"language-\\\"]::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"code[class*=\\\"language-\\\"]::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"pre[class*=\\\"language-\\\"] *::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"code[class*=\\\"language-\\\"] *::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \":not(pre) > code[class*=\\\"language-\\\"]\": {\n \"padding\": \".1em .3em\",\n \"borderRadius\": \".3em\",\n \"color\": \"#db4c69\",\n \"background\": \"#1e1e1e\"\n },\n \".namespace\": {\n \"Opacity\": \".7\"\n },\n \"doctype.doctype-tag\": {\n \"color\": \"#569CD6\"\n },\n \"doctype.name\": {\n \"color\": \"#9cdcfe\"\n },\n \"comment\": {\n \"color\": \"#6a9955\"\n },\n \"prolog\": {\n \"color\": \"#6a9955\"\n },\n \"punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-html .language-css .token.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-html .language-javascript .token.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \"property\": {\n \"color\": \"#9cdcfe\"\n },\n \"tag\": {\n \"color\": \"#569cd6\"\n },\n \"boolean\": {\n \"color\": \"#569cd6\"\n },\n \"number\": {\n \"color\": \"#b5cea8\"\n },\n \"constant\": {\n \"color\": \"#9cdcfe\"\n },\n \"symbol\": {\n \"color\": \"#b5cea8\"\n },\n \"inserted\": {\n \"color\": \"#b5cea8\"\n },\n \"unit\": {\n \"color\": \"#b5cea8\"\n },\n \"selector\": {\n \"color\": \"#d7ba7d\"\n },\n \"attr-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"string\": {\n \"color\": \"#ce9178\"\n },\n \"char\": {\n \"color\": \"#ce9178\"\n },\n \"builtin\": {\n \"color\": \"#ce9178\"\n },\n \"deleted\": {\n \"color\": \"#ce9178\"\n },\n \".language-css .token.string.url\": {\n \"textDecoration\": \"underline\"\n },\n \"operator\": {\n \"color\": \"#d4d4d4\"\n },\n \"entity\": {\n \"color\": \"#569cd6\"\n },\n \"operator.arrow\": {\n \"color\": \"#569CD6\"\n },\n \"atrule\": {\n \"color\": \"#ce9178\"\n },\n \"atrule.rule\": {\n \"color\": \"#c586c0\"\n },\n \"atrule.url\": {\n \"color\": \"#9cdcfe\"\n },\n \"atrule.url.function\": {\n \"color\": \"#dcdcaa\"\n },\n \"atrule.url.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \"keyword\": {\n \"color\": \"#569CD6\"\n },\n \"keyword.module\": {\n \"color\": \"#c586c0\"\n },\n \"keyword.control-flow\": {\n \"color\": \"#c586c0\"\n },\n \"function\": {\n \"color\": \"#dcdcaa\"\n },\n \"function.maybe-class-name\": {\n \"color\": \"#dcdcaa\"\n },\n \"regex\": {\n \"color\": \"#d16969\"\n },\n \"important\": {\n \"color\": \"#569cd6\"\n },\n \"italic\": {\n \"fontStyle\": \"italic\"\n },\n \"class-name\": {\n \"color\": \"#4ec9b0\"\n },\n \"maybe-class-name\": {\n \"color\": \"#4ec9b0\"\n },\n \"console\": {\n \"color\": \"#9cdcfe\"\n },\n \"parameter\": {\n \"color\": \"#9cdcfe\"\n },\n \"interpolation\": {\n \"color\": \"#9cdcfe\"\n },\n \"punctuation.interpolation-punctuation\": {\n \"color\": \"#569cd6\"\n },\n \"variable\": {\n \"color\": \"#9cdcfe\"\n },\n \"imports.maybe-class-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"exports.maybe-class-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"escape\": {\n \"color\": \"#d7ba7d\"\n },\n \"tag.punctuation\": {\n \"color\": \"#808080\"\n },\n \"cdata\": {\n \"color\": \"#808080\"\n },\n \"attr-value\": {\n \"color\": \"#ce9178\"\n },\n \"attr-value.punctuation\": {\n \"color\": \"#ce9178\"\n },\n \"attr-value.punctuation.attr-equals\": {\n \"color\": \"#d4d4d4\"\n },\n \"namespace\": {\n \"color\": \"#4ec9b0\"\n },\n \"pre[class*=\\\"language-javascript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-javascript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-jsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-jsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-typescript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-typescript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-tsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-tsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-css\\\"]\": {\n \"color\": \"#ce9178\"\n },\n \"code[class*=\\\"language-css\\\"]\": {\n \"color\": \"#ce9178\"\n },\n \"pre[class*=\\\"language-html\\\"]\": {\n \"color\": \"#d4d4d4\"\n },\n \"code[class*=\\\"language-html\\\"]\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-regex .token.anchor\": {\n \"color\": \"#dcdcaa\"\n },\n \".language-html .token.punctuation\": {\n \"color\": \"#808080\"\n },\n \"pre[class*=\\\"language-\\\"] > code[class*=\\\"language-\\\"]\": {\n \"position\": \"relative\",\n \"zIndex\": \"1\"\n },\n \".line-highlight.line-highlight\": {\n \"background\": \"#f7ebc6\",\n \"boxShadow\": \"inset 5px 0 0 #f7d87c\",\n \"zIndex\": \"0\"\n }\n};","import { useState, useEffect } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\n\ninterface MarkdownRendererProps {\n url: string;\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ url }) => {\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadMarkdown = async () => {\n try {\n setLoading(true);\n setError(null);\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('加载失败');\n }\n const text = await response.text();\n setContent(text);\n } catch (err) {\n setError('Markdown 文件加载失败');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadMarkdown();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-8\">\n <div className=\"max-w-4xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl p-8 border border-white/10\">\n <div className=\"prose prose-invert prose-lg max-w-none\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code({ node, inline, className, children, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '');\n return !inline && match ? (\n <SyntaxHighlighter\n style={vscDarkPlus}\n language={match[1]}\n PreTag=\"div\"\n className=\"rounded-lg\"\n {...props}\n >\n {String(children).replace(/\\n$/, '')}\n </SyntaxHighlighter>\n ) : (\n <code className=\"bg-white/10 px-1.5 py-0.5 rounded text-sm\" {...props}>\n {children}\n </code>\n );\n },\n h1: ({ children }) => (\n <h1 className=\"text-4xl font-bold mb-4 text-white border-b border-white/20 pb-2\">\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2 className=\"text-3xl font-bold mb-3 text-white mt-8\">{children}</h2>\n ),\n h3: ({ children }) => (\n <h3 className=\"text-2xl font-bold mb-2 text-white mt-6\">{children}</h3>\n ),\n p: ({ children }) => <p className=\"text-white/90 mb-4 leading-relaxed\">{children}</p>,\n a: ({ href, children }) => (\n <a\n href={href}\n className=\"text-blue-400 hover:text-blue-300 underline\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </a>\n ),\n ul: ({ children }) => <ul className=\"list-disc list-inside mb-4 text-white/90\">{children}</ul>,\n ol: ({ children }) => <ol className=\"list-decimal list-inside mb-4 text-white/90\">{children}</ol>,\n li: ({ children }) => <li className=\"mb-1\">{children}</li>,\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-4 border-blue-500 pl-4 italic text-white/80 my-4\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-4\">\n <table className=\"min-w-full border border-white/20\">{children}</table>\n </div>\n ),\n th: ({ children }) => (\n <th className=\"border border-white/20 px-4 py-2 bg-white/10 text-white font-semibold\">\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className=\"border border-white/20 px-4 py-2 text-white/90\">{children}</td>\n ),\n hr: () => <hr className=\"border-white/20 my-6\" />,\n img: ({ src, alt }) => (\n <img src={src} alt={alt} className=\"rounded-lg max-w-full h-auto my-4\" />\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n </div>\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport { FileText } from 'lucide-react';\n\ninterface TextRendererProps {\n url: string;\n fileName: string;\n}\n\nconst getLanguageFromFileName = (fileName: string): string => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n const languageMap: Record<string, string> = {\n js: 'javascript',\n jsx: 'jsx',\n ts: 'typescript',\n tsx: 'tsx',\n py: 'python',\n java: 'java',\n cpp: 'cpp',\n c: 'c',\n cs: 'csharp',\n php: 'php',\n rb: 'ruby',\n go: 'go',\n rs: 'rust',\n swift: 'swift',\n kt: 'kotlin',\n scala: 'scala',\n sh: 'bash',\n bash: 'bash',\n zsh: 'bash',\n json: 'json',\n xml: 'xml',\n html: 'html',\n css: 'css',\n scss: 'scss',\n sass: 'sass',\n less: 'less',\n sql: 'sql',\n yaml: 'yaml',\n yml: 'yaml',\n toml: 'toml',\n ini: 'ini',\n conf: 'nginx',\n md: 'markdown',\n txt: 'text',\n };\n return languageMap[ext] || 'text';\n};\n\nexport const TextRenderer: React.FC<TextRendererProps> = ({ url, fileName }) => {\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const language = getLanguageFromFileName(fileName);\n\n useEffect(() => {\n const loadText = async () => {\n try {\n setLoading(true);\n setError(null);\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('加载失败');\n }\n const text = await response.text();\n setContent(text);\n } catch (err) {\n setError('文本文件加载失败');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadText();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-8\">\n <div className=\"max-w-6xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl border border-white/10 overflow-hidden\">\n {/* 文件头部 */}\n <div className=\"flex items-center gap-3 px-6 py-4 bg-white/5 border-b border-white/10\">\n <FileText className=\"w-5 h-5 text-white/70\" />\n <span className=\"text-white font-medium\">{fileName}</span>\n <span className=\"ml-auto text-xs text-white/50 uppercase\">{language}</span>\n </div>\n\n {/* 代码内容 */}\n <div className=\"text-sm\">\n {language === 'text' ? (\n <pre className=\"p-6 text-white/90 font-mono whitespace-pre-wrap break-words\">\n {content}\n </pre>\n ) : (\n <SyntaxHighlighter\n language={language}\n style={vscDarkPlus}\n showLineNumbers\n customStyle={{\n margin: 0,\n padding: '1.5rem',\n background: 'transparent',\n fontSize: '0.875rem',\n }}\n lineNumberStyle={{\n minWidth: '3em',\n paddingRight: '1em',\n color: 'rgba(255, 255, 255, 0.3)',\n userSelect: 'none',\n }}\n >\n {content}\n </SyntaxHighlighter>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n","import { FileQuestion, Download } from 'lucide-react';\n\ninterface UnsupportedRendererProps {\n fileName: string;\n fileType: string;\n onDownload: () => void;\n}\n\nexport const UnsupportedRenderer: React.FC<UnsupportedRendererProps> = ({\n fileName,\n fileType,\n onDownload,\n}) => {\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-8 gap-6\">\n <div className=\"w-32 h-32 rounded-full bg-white/10 flex items-center justify-center\">\n <FileQuestion className=\"w-16 h-16 text-white/70\" />\n </div>\n\n <div className=\"text-white text-center\">\n <p className=\"text-xl font-medium mb-2\">{fileName}</p>\n <p className=\"text-white/70\">不支持预览此文件类型 ({fileType})</p>\n </div>\n\n <button\n onClick={onDownload}\n 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\"\n >\n <Download className=\"w-5 h-5\" />\n 下载文件查看\n </button>\n </div>\n );\n};\n\n","import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n X,\n ZoomIn,\n ZoomOut,\n RotateCw,\n RotateCcw,\n Download,\n ChevronLeft,\n ChevronRight,\n Maximize2,\n Minimize2,\n RefreshCw,\n} from 'lucide-react';\nimport { PreviewFile, PreviewFileInput, FileType, CustomRenderer } from './types';\nimport { normalizeFiles } from './utils/fileNormalizer';\nimport { ImageRenderer } from './renderers/ImageRenderer';\nimport { PdfRenderer } from './renderers/PdfRenderer';\nimport { DocxRenderer } from './renderers/DocxRenderer';\nimport { XlsxRenderer } from './renderers/XlsxRenderer';\nimport { PptxRenderer } from './renderers/PptxRenderer';\nimport { VideoRenderer } from './renderers/VideoRenderer';\nimport { AudioRenderer } from './renderers/AudioRenderer';\nimport { MarkdownRenderer } from './renderers/MarkdownRenderer';\nimport { TextRenderer } from './renderers/TextRenderer';\nimport { UnsupportedRenderer } from './renderers/UnsupportedRenderer';\n\ninterface FilePreviewModalProps {\n files: PreviewFileInput[];\n currentIndex: number;\n isOpen: boolean;\n onClose: () => void;\n onNavigate?: (index: number) => void;\n customRenderers?: CustomRenderer[];\n}\n\nconst getFileType = (file: PreviewFile): FileType => {\n const ext = file.name.split('.').pop()?.toLowerCase() || '';\n const mimeType = file.type.toLowerCase();\n\n if (mimeType.startsWith('image/') || ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(ext)) {\n return 'image';\n }\n if (mimeType.includes('pdf') || ext === 'pdf') {\n return 'pdf';\n }\n if (mimeType.includes('wordprocessingml') || ext === 'docx') {\n return 'docx';\n }\n if (mimeType.includes('spreadsheetml') || ext === 'xlsx') {\n return 'xlsx';\n }\n if (mimeType.includes('presentationml') || ext === 'pptx' || ext === 'ppt') {\n return 'pptx';\n }\n if (mimeType.startsWith('video/') || ['mp4', 'webm', 'ogg', 'ogv', 'mov', 'avi', 'mkv', 'm4v', '3gp', 'flv'].includes(ext)) {\n return 'video';\n }\n if (mimeType.startsWith('audio/') || ['mp3', 'wav', 'ogg', 'm4a', 'flac', 'aac'].includes(ext)) {\n return 'audio';\n }\n if (ext === 'md' || ext === 'markdown') {\n return 'markdown';\n }\n // 文本文件和代码文件\n const textExtensions = [\n 'txt', 'log', 'csv',\n 'js', 'jsx', 'ts', 'tsx', 'json',\n 'py', 'java', 'cpp', 'c', 'h', 'cs', 'php', 'rb', 'go', 'rs', 'swift', 'kt',\n 'html', 'css', 'scss', 'sass', 'less',\n 'xml', 'yaml', 'yml', 'toml', 'ini', 'conf',\n 'sh', 'bash', 'zsh', 'sql',\n ];\n if (mimeType.startsWith('text/') || textExtensions.includes(ext)) {\n return 'text';\n }\n return 'unsupported';\n};\n\nexport const FilePreviewModal: React.FC<FilePreviewModalProps> = ({\n files,\n currentIndex,\n isOpen,\n onClose,\n onNavigate,\n customRenderers = [],\n}) => {\n const [zoom, setZoom] = useState(1);\n const [rotation, setRotation] = useState(0);\n const [currentPage, setCurrentPage] = useState(1);\n const [, setTotalPages] = useState(1); // PDF 总页数,由 PdfRenderer 更新\n\n // 标准化文件输入\n const normalizedFiles = useMemo(() => normalizeFiles(files), [files]);\n\n const currentFile = normalizedFiles[currentIndex];\n\n // 检查是否有自定义渲染器匹配当前文件\n const customRenderer = useMemo(() => {\n if (!currentFile) return null;\n return customRenderers.find(renderer => renderer.test(currentFile));\n }, [currentFile, customRenderers]);\n\n const fileType = currentFile ? getFileType(currentFile) : 'unsupported';\n\n // 重置状态当文件改变时\n useEffect(() => {\n setZoom(1);\n setRotation(0);\n setCurrentPage(1);\n setTotalPages(1);\n }, [currentIndex]);\n\n // 键盘导航\n // 锁定 body 滚动\n useEffect(() => {\n if (isOpen) {\n // 保存原始的 overflow 值\n const originalOverflow = document.body.style.overflow;\n const originalPaddingRight = document.body.style.paddingRight;\n\n // 获取滚动条宽度\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n // 锁定滚动并补偿滚动条宽度\n document.body.style.overflow = 'hidden';\n if (scrollbarWidth > 0) {\n document.body.style.paddingRight = `${scrollbarWidth}px`;\n }\n\n return () => {\n // 恢复原始值\n document.body.style.overflow = originalOverflow;\n document.body.style.paddingRight = originalPaddingRight;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n } else if (e.key === 'ArrowLeft' && currentIndex > 0) {\n onNavigate?.(currentIndex - 1);\n } else if (e.key === 'ArrowRight' && currentIndex < normalizedFiles.length - 1) {\n onNavigate?.(currentIndex + 1);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, currentIndex, normalizedFiles.length, onClose, onNavigate]);\n\n const handleZoomIn = useCallback(() => {\n setZoom((prev) => Math.min(prev + 0.25, 5));\n }, []);\n\n const handleZoomOut = useCallback(() => {\n setZoom((prev) => Math.max(prev - 0.25, 0.5));\n }, []);\n\n const handleRotate = useCallback(() => {\n setRotation((prev) => prev + 90);\n }, []);\n\n const handleRotateLeft = useCallback(() => {\n setRotation((prev) => prev - 90);\n }, []);\n\n const handleFitToWidth = useCallback(() => {\n setZoom(1);\n setRotation(0);\n }, []);\n\n const handleOriginalSize = useCallback(() => {\n setZoom(1);\n }, []);\n\n const handleZoomChange = useCallback((newZoom: number) => {\n setZoom(newZoom);\n }, []);\n\n const handleReset = useCallback(() => {\n setZoom(1);\n setRotation(0);\n }, []);\n\n const handleDownload = useCallback(() => {\n if (!currentFile) return;\n const link = document.createElement('a');\n link.href = currentFile.url;\n link.download = currentFile.name;\n link.click();\n }, [currentFile]);\n\n if (!isOpen || !currentFile) return null;\n\n const showZoomControls = fileType === 'image' || fileType === 'pdf';\n const showRotateControl = fileType === 'image';\n\n const modalContent = (\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-md overflow-hidden\"\n onClick={onClose}\n onWheel={(e) => e.stopPropagation()}\n >\n {/* 主内容区域 */}\n <div\n className=\"relative w-full h-full flex flex-col overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 顶部工具栏 */}\n <motion.div\n initial={{ y: -100 }}\n animate={{ y: 0 }}\n exit={{ y: -100 }}\n className=\"absolute top-0 left-0 right-0 z-10 p-4\"\n >\n <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\">\n {/* 文件名 */}\n <div className=\"flex-1 min-w-0\">\n <h2 className=\"text-white font-medium text-lg truncate\">\n {currentFile.name}\n </h2>\n <p className=\"text-white/60 text-sm\">\n {currentIndex + 1} / {normalizedFiles.length}\n </p>\n </div>\n\n {/* 工具按钮 */}\n <div className=\"flex items-center gap-2 ml-4\">\n {showZoomControls && (\n <>\n <ToolbarButton\n icon={<ZoomOut className=\"w-5 h-5\" />}\n label=\"缩小\"\n onClick={handleZoomOut}\n disabled={zoom <= 0.5}\n />\n <span className=\"text-white/70 text-sm min-w-[4rem] text-center font-medium\">\n {Math.round(zoom * 100)}%\n </span>\n <ToolbarButton\n icon={<ZoomIn className=\"w-5 h-5\" />}\n label=\"放大\"\n onClick={handleZoomIn}\n disabled={zoom >= 5}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n <ToolbarButton\n icon={<Minimize2 className=\"w-5 h-5\" />}\n label=\"适应窗口\"\n onClick={handleFitToWidth}\n />\n <ToolbarButton\n icon={<Maximize2 className=\"w-5 h-5\" />}\n label=\"原始尺寸\"\n onClick={handleOriginalSize}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n {showRotateControl && (\n <>\n <ToolbarButton\n icon={<RotateCcw className=\"w-5 h-5\" />}\n label=\"向左旋转\"\n onClick={handleRotateLeft}\n />\n <ToolbarButton\n icon={<RotateCw className=\"w-5 h-5\" />}\n label=\"向右旋转\"\n onClick={handleRotate}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n {(showZoomControls || showRotateControl) && (\n <>\n <ToolbarButton\n icon={<RefreshCw className=\"w-5 h-5\" />}\n label=\"复原\"\n onClick={handleReset}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n <ToolbarButton\n icon={<Download className=\"w-5 h-5\" />}\n label=\"下载\"\n onClick={handleDownload}\n />\n\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n\n <ToolbarButton\n icon={<X className=\"w-5 h-5\" />}\n label=\"关闭\"\n onClick={onClose}\n />\n </div>\n </div>\n </motion.div>\n\n {/* 内容区域 */}\n <div className=\"flex-1 flex items-center justify-center pt-24 pb-8 overflow-auto\">\n {customRenderer ? (\n // 使用自定义渲染器\n customRenderer.render(currentFile)\n ) : (\n <>\n {fileType === 'image' && (\n <ImageRenderer\n url={currentFile.url}\n zoom={zoom}\n rotation={rotation}\n onZoomChange={handleZoomChange}\n />\n )}\n {fileType === 'pdf' && (\n <PdfRenderer\n url={currentFile.url}\n zoom={zoom}\n currentPage={currentPage}\n onPageChange={setCurrentPage}\n onTotalPagesChange={setTotalPages}\n />\n )}\n {fileType === 'docx' && <DocxRenderer url={currentFile.url} />}\n {fileType === 'xlsx' && <XlsxRenderer url={currentFile.url} />}\n {fileType === 'pptx' && <PptxRenderer url={currentFile.url} />}\n {fileType === 'video' && <VideoRenderer url={currentFile.url} />}\n {fileType === 'audio' && (\n <AudioRenderer url={currentFile.url} fileName={currentFile.name} />\n )}\n {fileType === 'markdown' && <MarkdownRenderer url={currentFile.url} />}\n {fileType === 'text' && (\n <TextRenderer url={currentFile.url} fileName={currentFile.name} />\n )}\n {fileType === 'unsupported' && (\n <UnsupportedRenderer\n fileName={currentFile.name}\n fileType={currentFile.type}\n onDownload={handleDownload}\n />\n )}\n </>\n )}\n </div>\n\n {/* 左右导航箭头 */}\n {normalizedFiles.length > 1 && (\n <>\n {currentIndex > 0 && (\n <motion.button\n initial={{ x: -100, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n exit={{ x: -100, opacity: 0 }}\n onClick={() => onNavigate?.(currentIndex - 1)}\n 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\"\n >\n <ChevronLeft className=\"w-6 h-6\" />\n </motion.button>\n )}\n\n {currentIndex < normalizedFiles.length - 1 && (\n <motion.button\n initial={{ x: 100, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n exit={{ x: 100, opacity: 0 }}\n onClick={() => onNavigate?.(currentIndex + 1)}\n 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\"\n >\n <ChevronRight className=\"w-6 h-6\" />\n </motion.button>\n )}\n </>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n );\n\n // 使用 Portal 将模态框渲染到 document.body\n return createPortal(modalContent, document.body);\n};\n\n// 工具栏按钮组件\ninterface ToolbarButtonProps {\n icon: React.ReactNode;\n label: string;\n onClick: () => void;\n disabled?: boolean;\n}\n\nconst ToolbarButton: React.FC<ToolbarButtonProps> = ({ icon, label, onClick, disabled }) => {\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n title={label}\n className={`p-2 rounded-lg transition-all ${disabled\n ? 'text-white/30 cursor-not-allowed'\n : 'text-white hover:bg-white/10 active:bg-white/20'\n }`}\n >\n {icon}\n </button>\n );\n};\n\n","// 导入样式\nimport './index.css';\n\n// 导入版本号\nimport packageJson from '../package.json';\n\n// 导出版本号\nexport const VERSION = packageJson.version;\n\n// 导出主组件\nexport { FilePreviewModal } from './FilePreviewModal';\n\n// 导出类型定义\nexport type {\n PreviewFile,\n PreviewFileLink,\n PreviewFileInput,\n FileType,\n ToolbarAction,\n PreviewState,\n CustomRenderer,\n} from './types';\n\n// 导出工具函数\nexport { normalizeFile, normalizeFiles } from './utils/fileNormalizer';\n\n// 导出 PDF.js 配置函数和类型\nexport { configurePdfjs, pdfjs } from './utils/pdfConfig';\nexport type { PdfConfigOptions } from './utils/pdfConfig';\n\n"],"names":["getFileNameFromUrl","url","fileName","inferMimeType","ext","_a","normalizeFile","input","index","normalizeFiles","inputs","ImageRenderer","zoom","rotation","onZoomChange","loaded","setLoaded","useState","error","setError","position","setPosition","isDragging","setIsDragging","dragStart","setDragStart","internalZoom","setInternalZoom","containerRef","useRef","useEffect","handleLoad","handleError","handleDoubleClick","handleWheel","useCallback","e","delta","prev","newZoom","handleMouseDown","handleMouseMove","handleMouseUp","jsxs","jsx","motion","configurePdfjs","options","workerSrc","pdfjs","cMapUrl","cMapPacked","PdfRenderer","currentPage","onPageChange","onTotalPagesChange","numPages","setNumPages","pageRefs","onDocumentLoadSuccess","onDocumentLoadError","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","pageElement","pageNumber","rect","containerRect","pageCenter","distance","setPageRef","element","Document","_","el","Page","DocxRenderer","html","setHtml","loading","setLoading","response","arrayBuffer","result","mammoth","err","XlsxRenderer","sheets","setSheets","activeSheet","setActiveSheet","workbook","XLSX","parsedSheets","name","worksheet","data","currentSheet","sheet","row","rowIndex","cell","cellIndex","PptxRenderer","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","isInitialRender","updateDimensions","initialDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadPptx","previewErr","timer","Presentation","getVideoType","VideoRenderer","isLoading","setIsLoading","videoRef","playerRef","videoElement","videoType","player","videojs","AudioRenderer","isPlaying","setIsPlaying","currentTime","setCurrentTime","duration","setDuration","volume","setVolume","isMuted","setIsMuted","audioRef","audio","updateTime","updateDuration","handleEnded","handleCanPlay","togglePlay","handleSeek","time","handleVolumeChange","vol","toggleMute","skip","seconds","formatTime","minutes","Music","SkipBack","Pause","Play","SkipForward","VolumeX","Volume2","vscDarkPlus","MarkdownRenderer","content","setContent","text","ReactMarkdown","remarkGfm","node","inline","className","children","props","match","SyntaxHighlighter","href","src","alt","getLanguageFromFileName","TextRenderer","language","FileText","UnsupportedRenderer","fileType","onDownload","FileQuestion","Download","getFileType","file","mimeType","textExtensions","FilePreviewModal","files","currentIndex","isOpen","onClose","onNavigate","customRenderers","setZoom","setRotation","setCurrentPage","setTotalPages","normalizedFiles","useMemo","currentFile","customRenderer","renderer","originalOverflow","originalPaddingRight","scrollbarWidth","handleKeyDown","handleZoomIn","handleZoomOut","handleRotate","handleRotateLeft","handleFitToWidth","handleOriginalSize","handleZoomChange","handleReset","handleDownload","link","showZoomControls","showRotateControl","modalContent","AnimatePresence","Fragment","ToolbarButton","ZoomOut","ZoomIn","Minimize2","Maximize2","RotateCcw","RotateCw","RefreshCw","X","ChevronLeft","ChevronRight","createPortal","icon","label","onClick","disabled","VERSION","packageJson"],"mappings":"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QAAA,CAAA,CACZ,EACF,CAEJ,EClOAgJ,EAAe,CACb,0BAA6B,CAC3B,MAAS,UACT,SAAY,OACZ,WAAc,OACd,WAAc,kFACd,UAAa,MACb,UAAa,OACb,WAAc,MACd,YAAe,SACf,UAAa,SACb,WAAc,MACd,WAAc,IACd,SAAY,IACZ,QAAW,IACX,cAAiB,OACjB,WAAc,OACd,UAAa,OACb,QAAW,OACX,QAAW,MACX,OAAU,SACV,SAAY,OACZ,WAAc,SAClB,EACE,2BAA8B,CAC5B,MAAS,UACT,SAAY,OACZ,WAAc,OACd,WAAc,kFACd,UAAa,MACb,UAAa,OACb,WAAc,MACd,YAAe,SACf,UAAa,SACb,WAAc,MACd,WAAc,IACd,SAAY,IACZ,QAAW,IACX,cAAiB,OACjB,WAAc,OACd,UAAa,OACb,QAAW,MACf,EACE,qCAAwC,CACtC,WAAc,OACd,WAAc,SAClB,EACE,sCAAyC,CACvC,WAAc,OACd,WAAc,SAClB,EACE,uCAA0C,CACxC,WAAc,OACd,WAAc,SAClB,EACE,wCAA2C,CACzC,WAAc,OACd,WAAc,SAClB,EACE,uCAA0C,CACxC,QAAW,YACX,aAAgB,OAChB,MAAS,UACT,WAAc,SAClB,EACE,aAAc,CACZ,QAAW,IACf,EACE,sBAAuB,CACrB,MAAS,SACb,EACE,eAAgB,CACd,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,YAAe,CACb,MAAS,SACb,EACE,kDAAmD,CACjD,MAAS,SACb,EACE,yDAA0D,CACxD,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,IAAO,CACL,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,KAAQ,CACN,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,YAAa,CACX,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,KAAQ,CACN,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,kCAAmC,CACjC,eAAkB,WACtB,EACE,SAAY,CACV,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,iBAAkB,CAChB,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,cAAe,CACb,MAAS,SACb,EACE,aAAc,CACZ,MAAS,SACb,EACE,sBAAuB,CACrB,MAAS,SACb,EACE,yBAA0B,CACxB,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,iBAAkB,CAChB,MAAS,SACb,EACE,uBAAwB,CACtB,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,4BAA6B,CAC3B,MAAS,SACb,EACE,MAAS,CACP,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,OAAU,CACR,UAAa,QACjB,EACE,aAAc,CACZ,MAAS,SACb,EACE,mBAAoB,CAClB,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,cAAiB,CACf,MAAS,SACb,EACE,wCAAyC,CACvC,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,2BAA4B,CAC1B,MAAS,SACb,EACE,2BAA4B,CAC1B,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,kBAAmB,CACjB,MAAS,SACb,EACE,MAAS,CACP,MAAS,SACb,EACE,aAAc,CACZ,MAAS,SACb,EACE,yBAA0B,CACxB,MAAS,SACb,EACE,qCAAsC,CACpC,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,oCAAuC,CACrC,MAAS,SACb,EACE,qCAAwC,CACtC,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,oCAAuC,CACrC,MAAS,SACb,EACE,qCAAwC,CACtC,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,8BAAiC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","x_google_ignoreList":[9]}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/fileNormalizer.ts","../src/renderers/ImageRenderer.tsx","../src/utils/pdfConfig.ts","../src/renderers/PdfRenderer.tsx","../src/renderers/DocxRenderer.tsx","../src/renderers/XlsxRenderer.tsx","../src/renderers/PptxRenderer.tsx","../src/renderers/VideoRenderer.tsx","../src/renderers/AudioRenderer.tsx","../../../node_modules/.pnpm/react-syntax-highlighter@16.1.0_react@18.3.1/node_modules/react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js","../src/renderers/MarkdownRenderer.tsx","../src/renderers/TextRenderer.tsx","../src/renderers/UnsupportedRenderer.tsx","../src/FilePreviewModal.tsx","../src/index.ts"],"sourcesContent":["import { PreviewFile, PreviewFileInput } from '../types';\n\n/**\n * 从 URL 字符串中提取文件名\n */\nfunction getFileNameFromUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n const pathname = urlObj.pathname;\n const fileName = pathname.split('/').pop() || 'file';\n return decodeURIComponent(fileName);\n } catch {\n // 如果不是有效的 URL,尝试从路径中提取\n const fileName = url.split('/').pop() || 'file';\n return decodeURIComponent(fileName);\n }\n}\n\n/**\n * 从文件名中推断 MIME 类型\n */\nfunction inferMimeType(fileName: string): string {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n \n const mimeTypes: Record<string, string> = {\n // 图片\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n \n // 视频\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/x-m4v',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n \n // 音频\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n m4a: 'audio/mp4',\n aac: 'audio/aac',\n flac: 'audio/flac',\n \n // 文档\n pdf: 'application/pdf',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n ppt: 'application/vnd.ms-powerpoint',\n \n // 文本\n txt: 'text/plain',\n md: 'text/markdown',\n markdown: 'text/markdown',\n json: 'application/json',\n xml: 'application/xml',\n html: 'text/html',\n css: 'text/css',\n js: 'text/javascript',\n ts: 'text/typescript',\n jsx: 'text/javascript',\n tsx: 'text/typescript',\n py: 'text/x-python',\n java: 'text/x-java',\n cpp: 'text/x-c++src',\n c: 'text/x-csrc',\n cs: 'text/x-csharp',\n php: 'text/x-php',\n rb: 'text/x-ruby',\n go: 'text/x-go',\n rs: 'text/x-rust',\n yaml: 'text/yaml',\n yml: 'text/yaml',\n };\n \n return mimeTypes[ext] || 'application/octet-stream';\n}\n\n/**\n * 标准化文件输入为 PreviewFile 格式\n * 支持三种输入类型:\n * 1. File 对象(原生浏览器 File)\n * 2. PreviewFileLink 对象(包含 name, url, type 等属性)\n * 3. string(HTTP URL)\n */\nexport function normalizeFile(input: PreviewFileInput, index: number = 0): PreviewFile {\n // 情况 1: 原生 File 对象\n if (input instanceof File) {\n return {\n id: `file-${Date.now()}-${index}`,\n name: input.name,\n url: URL.createObjectURL(input),\n type: input.type || inferMimeType(input.name),\n size: input.size,\n };\n }\n \n // 情况 2: 字符串 URL\n if (typeof input === 'string') {\n const fileName = getFileNameFromUrl(input);\n return {\n id: `url-${Date.now()}-${index}`,\n name: fileName,\n url: input,\n type: inferMimeType(fileName),\n };\n }\n \n // 情况 3: PreviewFileLink 对象\n return {\n id: input.id || `link-${Date.now()}-${index}`,\n name: input.name,\n url: input.url,\n type: input.type || inferMimeType(input.name),\n size: input.size,\n };\n}\n\n/**\n * 批量标准化文件输入\n */\nexport function normalizeFiles(inputs: PreviewFileInput[]): PreviewFile[] {\n return inputs.map((input, index) => normalizeFile(input, index));\n}\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { motion } from 'framer-motion';\n\ninterface ImageRendererProps {\n url: string;\n zoom: number;\n rotation: number;\n onZoomChange?: (zoom: number) => void;\n}\n\nexport const ImageRenderer: React.FC<ImageRendererProps> = ({\n url,\n zoom,\n rotation,\n onZoomChange\n}) => {\n const [loaded, setLoaded] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [position, setPosition] = useState({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [internalZoom, setInternalZoom] = useState(1); // 内部缩放状态\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setLoaded(false);\n setError(null);\n setPosition({ x: 0, y: 0 });\n setInternalZoom(1);\n }, [url]);\n\n // 当外部 zoom 改变时,同步内部 zoom\n useEffect(() => {\n setInternalZoom(zoom);\n }, [zoom]);\n\n // 重置位置当缩放或旋转改变时\n useEffect(() => {\n setPosition({ x: 0, y: 0 });\n }, [zoom, rotation]);\n\n const handleLoad = () => {\n setLoaded(true);\n };\n\n const handleError = () => {\n setError('图片加载失败');\n setLoaded(true);\n };\n\n const handleDoubleClick = () => {\n // 双击重置位置\n setPosition({ x: 0, y: 0 });\n };\n\n // 鼠标滚轮缩放\n const handleWheel = useCallback((e: React.WheelEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const delta = e.deltaY > 0 ? -0.1 : 0.1;\n setInternalZoom(prev => {\n const newZoom = Math.max(0.01, Math.min(10, prev + delta)); // 限制缩放范围 0.01-10\n // 同步缩放比例到父组件\n if (onZoomChange) {\n onZoomChange(newZoom);\n }\n return newZoom;\n });\n }, [onZoomChange]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (e.button !== 0) return; // 只响应左键\n setIsDragging(true);\n setDragStart({\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n });\n }, [position]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!isDragging) return;\n setPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n });\n }, [isDragging, dragStart]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"flex items-center justify-center w-full h-full overflow-hidden\"\n onWheel={handleWheel}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n style={{ cursor: isDragging ? 'grabbing' : 'grab' }}\n >\n {!loaded && !error && (\n <div className=\"flex items-center justify-center\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n )}\n\n {error && (\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n )}\n\n <motion.img\n src={url}\n alt=\"Preview\"\n className={`max-w-none select-none ${!loaded ? 'hidden' : ''}`}\n style={{\n transform: `translate(${position.x}px, ${position.y}px) scale(${internalZoom}) rotate(${rotation}deg)`,\n transformOrigin: 'center',\n transition: isDragging ? 'none' : 'transform 0.3s ease-out',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onDoubleClick={handleDoubleClick}\n initial={{ opacity: 0 }}\n animate={{ opacity: loaded ? 1 : 0 }}\n transition={{ duration: 0.3 }}\n draggable={false}\n />\n </div>\n );\n};\n\n","import { pdfjs } from 'react-pdf';\n\n/**\n * PDF.js Worker 配置选项\n */\nexport interface PdfConfigOptions {\n /**\n * PDF.js worker 文件路径\n * 默认使用 CDN: `https://unpkg.com/pdfjs-dist@${version}/build/pdf.worker.min.mjs`\n */\n workerSrc?: string;\n \n /**\n * CMap 文件目录路径\n * 默认使用 CDN: `https://unpkg.com/pdfjs-dist@${version}/cmaps/`\n */\n cMapUrl?: string;\n \n /**\n * 是否使用压缩的 CMap 文件\n * 默认: true\n */\n cMapPacked?: boolean;\n}\n\n/**\n * 配置 PDF.js\n *\n * @example\n * ```ts\n * // 使用本地静态文件(推荐用于生产环境)\n * configurePdfjs({\n * workerSrc: '/pdfjs/pdf.worker.min.mjs',\n * cMapUrl: '/pdfjs/cmaps/',\n * cMapPacked: true\n * });\n * ```\n *\n * @example\n * ```ts\n * // 使用 CDN(默认配置)\n * configurePdfjs(); // 自动使用 unpkg CDN\n * ```\n */\nexport function configurePdfjs(options?: PdfConfigOptions) {\n if (typeof window === 'undefined') return;\n\n const {\n workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`,\n cMapUrl = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n cMapPacked = true\n } = options || {};\n\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n // @ts-ignore - cMapUrl 和 cMapPacked 在 react-pdf 的类型定义中不存在,但在运行时可用\n pdfjs.GlobalWorkerOptions.cMapUrl = cMapUrl;\n // @ts-ignore\n pdfjs.GlobalWorkerOptions.cMapPacked = cMapPacked;\n}\n\n// 默认使用 CDN 配置\nconfigurePdfjs();\n\nexport { pdfjs };\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { Document, Page } from 'react-pdf';\nimport 'react-pdf/dist/esm/Page/AnnotationLayer.css';\nimport 'react-pdf/dist/esm/Page/TextLayer.css';\n\n// 导入 PDF.js 配置\nimport '../utils/pdfConfig';\n\ninterface PdfRendererProps {\n url: string;\n zoom: number;\n currentPage: number;\n onPageChange: (page: number) => void;\n onTotalPagesChange: (total: number) => void;\n}\n\nexport const PdfRenderer: React.FC<PdfRendererProps> = ({\n url,\n zoom,\n currentPage,\n onPageChange,\n onTotalPagesChange,\n}) => {\n const [numPages, setNumPages] = useState<number>(0);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const pageRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n useEffect(() => {\n setError(null);\n }, [url]);\n\n const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {\n setNumPages(numPages);\n onTotalPagesChange(numPages);\n onPageChange(1);\n };\n\n const onDocumentLoadError = (error: Error) => {\n console.error('PDF 加载错误:', error);\n setError('PDF 文件加载失败');\n };\n\n // 滚动时更新当前页码\n const handleScroll = useCallback(() => {\n if (!containerRef.current) return;\n\n const container = containerRef.current;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n // 找到当前可见的页面\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageRefs.current.forEach((pageElement, pageNumber) => {\n const rect = pageElement.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const pageCenter = rect.top - containerRect.top + rect.height / 2 + scrollTop;\n const distance = Math.abs(pageCenter - scrollCenter);\n\n if (distance < minDistance) {\n minDistance = distance;\n currentVisiblePage = pageNumber;\n }\n });\n\n if (currentVisiblePage !== currentPage) {\n onPageChange(currentVisiblePage);\n }\n }, [currentPage, onPageChange]);\n\n // 监听滚动事件\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [handleScroll]);\n\n // 设置页面引用\n const setPageRef = useCallback((pageNumber: number, element: HTMLDivElement | null) => {\n if (element) {\n pageRefs.current.set(pageNumber, element);\n } else {\n pageRefs.current.delete(pageNumber);\n }\n }, []);\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col items-center w-full h-full overflow-auto py-4 md:py-8 px-2 md:px-4\"\n >\n {error && (\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n )}\n\n {!error && (\n <Document\n file={url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onDocumentLoadError}\n loading={\n <div className=\"flex items-center justify-center min-h-screen\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {Array.from(new Array(numPages), (_, index) => {\n const pageNumber = index + 1;\n return (\n <div\n key={`page_${pageNumber}`}\n ref={(el) => setPageRef(pageNumber, el)}\n className=\"relative\"\n >\n <Page\n pageNumber={pageNumber}\n scale={zoom}\n loading={\n <div className=\"flex items-center justify-center p-8 bg-white/5 rounded-lg min-h-[600px]\">\n <div className=\"w-8 h-8 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n }\n renderTextLayer={true}\n renderAnnotationLayer={true}\n className=\"shadow-2xl\"\n />\n {/* 页码标签 */}\n <div className=\"absolute top-2 right-2 bg-black/60 backdrop-blur-sm text-white text-xs px-3 py-1 rounded-full\">\n {pageNumber}\n </div>\n </div>\n );\n })}\n </div>\n </Document>\n )}\n\n {/* 底部页码指示器 */}\n {numPages > 0 && (\n <div className=\"sticky bottom-2 md:bottom-4 mt-4 md:mt-8 bg-black/60 backdrop-blur-xl text-white px-4 py-2 md:px-6 md:py-3 rounded-full text-xs md:text-sm font-medium shadow-2xl border border-white/10\">\n 第 {currentPage} 页 / 共 {numPages} 页\n </div>\n )}\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport mammoth from 'mammoth';\n\ninterface DocxRendererProps {\n url: string;\n}\n\nexport const DocxRenderer: React.FC<DocxRendererProps> = ({ url }) => {\n const [html, setHtml] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadDocx = async () => {\n setLoading(true);\n setError(null);\n setHtml('');\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const result = await mammoth.convertToHtml({ arrayBuffer });\n setHtml(result.value);\n } catch (err) {\n console.error('Docx 解析错误:', err);\n setError('Word 文档解析失败');\n } finally {\n setLoading(false);\n }\n };\n\n loadDocx();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-4 md:p-8\">\n <div\n className=\"max-w-full md:max-w-4xl mx-auto bg-white rounded-lg shadow-2xl p-6 md:p-12\"\n dangerouslySetInnerHTML={{ __html: html }}\n style={{\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.6',\n color: '#333',\n }}\n />\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport * as XLSX from 'xlsx';\n\ninterface XlsxRendererProps {\n url: string;\n}\n\nexport const XlsxRenderer: React.FC<XlsxRendererProps> = ({ url }) => {\n const [sheets, setSheets] = useState<{ name: string; data: unknown[] }[]>([]);\n const [activeSheet, setActiveSheet] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadXlsx = async () => {\n setLoading(true);\n setError(null);\n setSheets([]);\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const workbook = XLSX.read(arrayBuffer, { type: 'array' });\n\n const parsedSheets = workbook.SheetNames.map((name) => {\n const worksheet = workbook.Sheets[name];\n const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 });\n return { name, data };\n });\n\n setSheets(parsedSheets);\n setActiveSheet(0);\n } catch (err) {\n console.error('Excel 解析错误:', err);\n setError('Excel 文件解析失败');\n } finally {\n setLoading(false);\n }\n };\n\n loadXlsx();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n const currentSheet = sheets[activeSheet];\n\n return (\n <div className=\"w-full h-full flex flex-col overflow-hidden\">\n {/* Sheet Tabs */}\n {sheets.length > 1 && (\n <div className=\"flex gap-1 md:gap-2 p-2 md:p-4 bg-black/20 backdrop-blur-sm overflow-x-auto border-b border-white/10 scrollbar-hide\">\n {sheets.map((sheet, index) => (\n <button\n key={index}\n onClick={() => setActiveSheet(index)}\n className={`px-3 py-1.5 md:px-4 md:py-2 rounded-lg text-xs md:text-sm font-medium transition-all flex-shrink-0 ${activeSheet === index\n ? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-lg'\n : 'bg-white/10 text-white hover:bg-white/20'\n }`}\n >\n {sheet.name}\n </button>\n ))}\n </div>\n )}\n\n {/* Table */}\n <div className=\"flex-1 overflow-auto p-2 md:p-8\">\n <div className=\"inline-block min-w-full bg-gradient-to-br from-gray-800/90 to-gray-900/90 backdrop-blur-xl rounded-xl md:rounded-2xl shadow-2xl overflow-hidden border border-white/10\">\n <table className=\"min-w-full divide-y divide-white/10\">\n <tbody className=\"divide-y divide-white/10\">\n {currentSheet?.data.map((row, rowIndex) => (\n <tr\n key={rowIndex}\n className={`transition-colors ${rowIndex === 0\n ? 'bg-gradient-to-r from-purple-500/20 to-pink-500/20 font-semibold'\n : 'hover:bg-white/5'\n }`}\n >\n {(row as unknown[]).map((cell, cellIndex) => (\n <td\n key={cellIndex}\n className=\"px-3 py-2 md:px-6 md:py-4 whitespace-nowrap text-xs md:text-sm text-gray-200 border-r border-white/10\"\n >\n {String(cell ?? '')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n );\n};\n\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { Presentation } from 'lucide-react';\nimport { init } from 'pptx-preview';\n\ninterface PptxRendererProps {\n url: string;\n}\n\nexport const PptxRenderer: React.FC<PptxRendererProps> = ({ url }) => {\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const previewerRef = useRef<ReturnType<typeof init> | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const arrayBufferRef = useRef<ArrayBuffer | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n // 计算容器尺寸\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 960, height: 540 };\n\n const containerWidth = containerRef.current.clientWidth;\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n\n console.log('计算尺寸:', { width: containerWidth, height });\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current) return;\n\n console.log('重新初始化预览器...');\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch (e) {\n console.error('销毁预览器失败:', e);\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n console.log('重新初始化使用尺寸:', currentDimensions);\n\n // 初始化新的预览器\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: currentDimensions.height,\n });\n\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n console.log('重新初始化成功');\n } catch (e) {\n console.error('重新初始化失败:', e);\n }\n }, [calculateDimensions]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n // 跳过初始渲染时的尺寸检查\n if (isInitialRender) {\n isInitialRender = false;\n const initialDimensions = calculateDimensions();\n lastDimensionsRef.current = initialDimensions;\n return;\n }\n\n const newDimensions = calculateDimensions();\n\n // 检查尺寸是否真正变化(至少变化10px才触发)\n const lastDimensions = lastDimensionsRef.current;\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) {\n console.log('尺寸变化太小,忽略');\n return; // 尺寸变化太小,不做任何操作\n }\n\n console.log('检测到尺寸变化:', {\n old: lastDimensions,\n new: newDimensions,\n diff: { width: widthDiff, height: heightDiff }\n });\n\n // 更新最后的尺寸\n lastDimensionsRef.current = newDimensions;\n\n // 清除之前的定时器\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // 防抖:800ms 后重新初始化预览器\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (previewerRef.current && arrayBufferRef.current) {\n console.log('尺寸变化,准备重新初始化');\n reinitializePreviewer();\n }\n }, 800);\n };\n\n // 创建 ResizeObserver\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n // 开始观察容器\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, reinitializePreviewer]);\n\n useEffect(() => {\n let isMounted = true;\n\n const loadPptx = async () => {\n if (!containerRef.current) {\n console.log('Container ref not ready');\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n console.log('开始加载 PPTX:', url);\n\n // 获取文件\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n arrayBufferRef.current = arrayBuffer; // 保存到 ref\n console.log('文件加载成功,大小:', arrayBuffer.byteLength);\n\n if (!isMounted) return;\n\n // 清空容器\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n console.log('使用尺寸:', currentDimensions);\n\n // 初始化 pptx 预览器\n console.log('初始化预览器...');\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: currentDimensions.height,\n });\n\n previewerRef.current = previewer;\n\n // 预览 PPTX\n console.log('开始预览...');\n previewer.preview(arrayBuffer)\n .then(() => {\n console.log('预览成功');\n if (isMounted) {\n setLoading(false);\n }\n })\n .catch((previewErr) => {\n console.error('预览失败:', previewErr);\n if (isMounted) {\n setError('PPT 文件预览失败');\n setLoading(false);\n }\n });\n } catch (err) {\n console.error('PPTX 解析错误:', err);\n if (isMounted) {\n setError(err instanceof Error ? err.message : 'PPT 文件解析失败');\n setLoading(false);\n }\n }\n };\n\n // 延迟执行以确保 DOM 已准备好\n const timer = setTimeout(() => {\n loadPptx();\n }, 100);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n arrayBufferRef.current = null;\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch (e) {\n console.error('销毁预览器失败:', e);\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions]);\n\n return (\n <div className=\"relative flex flex-col items-center w-full h-full pt-2 px-2 md:px-4\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-xl md:rounded-2xl\">\n <div className=\"text-center\">\n <div className=\"w-10 h-10 md:w-12 md:h-12 mx-auto mb-3 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n <p className=\"text-xs md:text-sm text-white/70 font-medium\">加载 PPT 中...</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm z-10 rounded-xl md:rounded-2xl\">\n <div className=\"text-center max-w-sm md:max-w-md px-4\">\n <div className=\"w-24 h-24 md:w-32 md:h-32 mx-auto mb-4 md:mb-6 rounded-2xl md:rounded-3xl bg-gradient-to-br from-orange-500 via-red-500 to-pink-500 flex items-center justify-center shadow-2xl\">\n <Presentation className=\"w-12 h-12 md:w-16 md:h-16 text-white\" />\n </div>\n <p className=\"text-lg md:text-xl text-white/90 mb-2 md:mb-3 font-medium\">PPT 预览</p>\n <p className=\"text-xs md:text-sm text-white/60 mb-4 md:mb-6\">\n {error || '浏览器暂不支持直接预览 PPT 文件'}\n </p>\n <a\n href={url}\n download\n className=\"inline-flex items-center gap-2 px-4 py-2 md:px-6 md:py-3 bg-gradient-to-r from-purple-500 to-pink-500 text-white text-sm md:text-base rounded-lg md:rounded-xl hover:scale-105 transition-all shadow-lg\"\n >\n <svg className=\"w-4 h-4 md:w-5 md:h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n 下载文件\n </a>\n <p className=\"text-xs text-white/40 mt-3 md:mt-4\">\n 提示:可以使用 Microsoft PowerPoint 或 WPS 打开\n </p>\n </div>\n </div>\n )}\n\n {/* PPT 容器 - 始终渲染 */}\n <div\n ref={containerRef}\n className=\"pptx-wrapper w-full max-w-full md:max-w-6xl\"\n />\n </div>\n );\n};\n\n","import { useRef, useEffect, useState } from 'react';\nimport videojs from 'video.js';\nimport 'video.js/dist/video-js.css';\n\ntype VideoJsPlayer = ReturnType<typeof videojs>;\n\ninterface VideoRendererProps {\n url: string;\n}\n\n// 根据 URL 获取视频 MIME 类型\nconst getVideoType = (url: string): string => {\n const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';\n const typeMap: Record<string, string> = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime', // MOV 使用 QuickTime MIME 类型\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/mp4',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n };\n return typeMap[ext] || 'video/mp4';\n};\n\nexport const VideoRenderer: React.FC<VideoRendererProps> = ({ url }) => {\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const videoRef = useRef<HTMLDivElement>(null);\n const playerRef = useRef<VideoJsPlayer | null>(null);\n\n useEffect(() => {\n // 确保 Video.js 播放器只初始化一次\n if (!playerRef.current && videoRef.current) {\n const videoElement = document.createElement('video-js');\n videoElement.classList.add('vjs-big-play-centered', 'vjs-theme-apple');\n videoRef.current.appendChild(videoElement);\n\n const videoType = getVideoType(url);\n\n // 为 MOV 格式提供多个 MIME 类型作为备用\n const sources = videoType === 'video/quicktime'\n ? [\n { src: url, type: 'video/quicktime' },\n { src: url, type: 'video/mp4' } // 备用方案\n ]\n : [{ src: url, type: videoType }];\n\n const player = videojs(videoElement, {\n controls: true,\n responsive: true,\n fluid: true,\n preload: 'auto',\n controlBar: {\n children: [\n 'playToggle',\n 'volumePanel',\n 'currentTimeDisplay',\n 'timeDivider',\n 'durationDisplay',\n 'progressControl',\n 'remainingTimeDisplay',\n 'fullscreenToggle'\n ],\n volumePanel: {\n inline: false\n }\n },\n html5: {\n vhs: {\n overrideNative: true\n },\n nativeVideoTracks: false,\n nativeAudioTracks: false,\n nativeTextTracks: false\n },\n sources\n });\n\n // 监听加载完成\n player.on('loadeddata', () => {\n setIsLoading(false);\n });\n\n player.on('error', () => {\n const error = player.error();\n console.error('Video.js error:', error);\n setError(`视频加载失败: ${error?.message || '未知错误'}`);\n setIsLoading(false);\n });\n\n playerRef.current = player;\n }\n }, [url]);\n\n // 清理函数\n useEffect(() => {\n const player = playerRef.current;\n\n return () => {\n if (player && !player.isDisposed()) {\n player.dispose();\n playerRef.current = null;\n }\n };\n }, []);\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-center\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-red-500/10 flex items-center justify-center\">\n <svg className=\"w-8 h-8 text-red-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </div>\n <p className=\"text-lg font-medium text-white/90 mb-2\">视频加载失败</p>\n <p className=\"text-sm text-white/60\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center justify-center w-full h-full p-4 md:p-8\">\n <div className=\"w-full max-w-full md:max-w-5xl relative\">\n {/* 加载状态 */}\n {isLoading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded-2xl z-10\">\n <div className=\"text-center\">\n <div className=\"w-12 h-12 mx-auto mb-3 border-3 border-white/20 border-t-white rounded-full animate-spin\" />\n <p className=\"text-sm text-white/70 font-medium\">加载视频中...</p>\n </div>\n </div>\n )}\n\n {/* 视频播放器容器 */}\n <div\n ref={videoRef}\n className=\"overflow-hidden\"\n style={{\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)'\n }}\n />\n </div>\n </div>\n );\n};\n\n","import { useState, useRef, useEffect } from 'react';\nimport { Music, Play, Pause, Volume2, VolumeX, SkipBack, SkipForward } from 'lucide-react';\n\ninterface AudioRendererProps {\n url: string;\n fileName: string;\n}\n\nexport const AudioRenderer: React.FC<AudioRendererProps> = ({ url, fileName }) => {\n const [error, setError] = useState<string | null>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [volume, setVolume] = useState(1);\n const [isMuted, setIsMuted] = useState(false);\n const audioRef = useRef<HTMLAudioElement>(null);\n\n useEffect(() => {\n const audio = audioRef.current;\n if (!audio) return;\n\n const updateTime = () => {\n if (!isNaN(audio.currentTime)) {\n setCurrentTime(audio.currentTime);\n }\n };\n\n const updateDuration = () => {\n if (!isNaN(audio.duration) && isFinite(audio.duration)) {\n setDuration(audio.duration);\n }\n };\n\n const handleEnded = () => setIsPlaying(false);\n const handleCanPlay = () => updateDuration();\n\n audio.addEventListener('timeupdate', updateTime);\n audio.addEventListener('loadedmetadata', updateDuration);\n audio.addEventListener('durationchange', updateDuration);\n audio.addEventListener('canplay', handleCanPlay);\n audio.addEventListener('ended', handleEnded);\n\n // 立即尝试获取时长\n if (audio.readyState >= 1) {\n updateDuration();\n }\n\n return () => {\n audio.removeEventListener('timeupdate', updateTime);\n audio.removeEventListener('loadedmetadata', updateDuration);\n audio.removeEventListener('durationchange', updateDuration);\n audio.removeEventListener('canplay', handleCanPlay);\n audio.removeEventListener('ended', handleEnded);\n };\n }, []);\n\n const togglePlay = () => {\n if (audioRef.current) {\n if (isPlaying) {\n audioRef.current.pause();\n } else {\n audioRef.current.play();\n }\n setIsPlaying(!isPlaying);\n }\n };\n\n const handleSeek = (e: React.ChangeEvent<HTMLInputElement>) => {\n const time = parseFloat(e.target.value);\n setCurrentTime(time);\n if (audioRef.current) {\n audioRef.current.currentTime = time;\n }\n };\n\n const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const vol = parseFloat(e.target.value);\n setVolume(vol);\n if (audioRef.current) {\n audioRef.current.volume = vol;\n }\n if (vol > 0) setIsMuted(false);\n };\n\n const toggleMute = () => {\n if (audioRef.current) {\n audioRef.current.muted = !isMuted;\n setIsMuted(!isMuted);\n }\n };\n\n const skip = (seconds: number) => {\n if (audioRef.current) {\n audioRef.current.currentTime += seconds;\n }\n };\n\n const formatTime = (time: number) => {\n if (!isFinite(time) || isNaN(time) || time < 0) return '0:00';\n const minutes = Math.floor(time / 60);\n const seconds = Math.floor(time % 60);\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n };\n\n const handleError = () => {\n setError('音频加载失败');\n };\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-4 md:p-8 gap-4 md:gap-8\">\n {/* 音频封面 */}\n <div className=\"w-48 h-48 md:w-64 md: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\">\n <Music className=\"w-24 h-24 md:w-32 md:h-32 text-white\" />\n </div>\n\n {/* 文件名 */}\n <div className=\"text-white text-center max-w-sm md:max-w-md px-4\">\n <p className=\"text-xl md:text-2xl font-medium mb-1 truncate\">{fileName}</p>\n <p className=\"text-xs md:text-sm text-white/60\">音频文件</p>\n </div>\n\n {/* 播放控制器 */}\n <div className=\"w-full max-w-sm md:max-w-md bg-white/10 backdrop-blur-xl rounded-2xl p-4 md:p-6 border border-white/20\">\n {/* 进度条 */}\n <div className=\"mb-4\">\n <div className=\"relative h-4 flex items-center\">\n {/* 进度条背景轨道 */}\n <div className=\"absolute w-full h-[6px] bg-white/20 rounded-full\" />\n {/* 已播放进度覆盖层 */}\n <div\n 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\"\n style={{\n width: `${duration > 0 ? (currentTime / duration) * 100 : (currentTime > 100 ? 100 : currentTime)}%`\n }}\n />\n {/* 进度条滑块 */}\n <input\n type=\"range\"\n min=\"0\"\n max={duration > 0 ? duration : 100 + (currentTime > 100 ? currentTime % 100 : 0)}\n value={currentTime}\n onChange={handleSeek}\n className=\"audio-slider absolute w-full\"\n />\n </div>\n <div className=\"flex justify-between text-xs text-white/60 mt-3\">\n <span>{formatTime(currentTime)}</span>\n <span>{formatTime(duration)}</span>\n </div>\n </div>\n\n {/* 控制按钮 */}\n <div className=\"flex items-center justify-center gap-4 mb-4\">\n <button\n onClick={() => skip(-10)}\n className=\"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all\"\n >\n <SkipBack className=\"w-5 h-5\" />\n </button>\n\n <button\n onClick={togglePlay}\n 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\"\n >\n {isPlaying ? <Pause className=\"w-6 h-6\" /> : <Play className=\"w-6 h-6 ml-1\" />}\n </button>\n\n <button\n onClick={() => skip(10)}\n className=\"w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-all\"\n >\n <SkipForward className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* 音量控制 */}\n <div className=\"flex items-center gap-3\">\n <button\n onClick={toggleMute}\n className=\"text-white/80 hover:text-white transition-colors\"\n >\n {isMuted || volume === 0 ? <VolumeX className=\"w-5 h-5\" /> : <Volume2 className=\"w-5 h-5\" />}\n </button>\n <div className=\"flex-1 relative h-3 flex items-center\">\n {/* 音量条背景轨道 */}\n <div className=\"absolute w-full h-[4px] bg-white/20 rounded-full\" />\n {/* 音量覆盖层 */}\n <div\n className=\"absolute h-[4px] bg-purple-500 rounded-full transition-all duration-100 pointer-events-none\"\n style={{\n width: `${(isMuted ? 0 : volume) * 100}%`\n }}\n />\n {/* 音量滑块 */}\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n value={isMuted ? 0 : volume}\n onChange={handleVolumeChange}\n className=\"volume-slider absolute w-full\"\n />\n </div>\n </div>\n </div>\n\n {/* 隐藏的 audio 元素 */}\n <audio\n ref={audioRef}\n src={url}\n onError={handleError}\n className=\"hidden\"\n />\n </div>\n );\n};\n\n","export default {\n \"pre[class*=\\\"language-\\\"]\": {\n \"color\": \"#d4d4d4\",\n \"fontSize\": \"13px\",\n \"textShadow\": \"none\",\n \"fontFamily\": \"Menlo, Monaco, Consolas, \\\"Andale Mono\\\", \\\"Ubuntu Mono\\\", \\\"Courier New\\\", monospace\",\n \"direction\": \"ltr\",\n \"textAlign\": \"left\",\n \"whiteSpace\": \"pre\",\n \"wordSpacing\": \"normal\",\n \"wordBreak\": \"normal\",\n \"lineHeight\": \"1.5\",\n \"MozTabSize\": \"4\",\n \"OTabSize\": \"4\",\n \"tabSize\": \"4\",\n \"WebkitHyphens\": \"none\",\n \"MozHyphens\": \"none\",\n \"msHyphens\": \"none\",\n \"hyphens\": \"none\",\n \"padding\": \"1em\",\n \"margin\": \".5em 0\",\n \"overflow\": \"auto\",\n \"background\": \"#1e1e1e\"\n },\n \"code[class*=\\\"language-\\\"]\": {\n \"color\": \"#d4d4d4\",\n \"fontSize\": \"13px\",\n \"textShadow\": \"none\",\n \"fontFamily\": \"Menlo, Monaco, Consolas, \\\"Andale Mono\\\", \\\"Ubuntu Mono\\\", \\\"Courier New\\\", monospace\",\n \"direction\": \"ltr\",\n \"textAlign\": \"left\",\n \"whiteSpace\": \"pre\",\n \"wordSpacing\": \"normal\",\n \"wordBreak\": \"normal\",\n \"lineHeight\": \"1.5\",\n \"MozTabSize\": \"4\",\n \"OTabSize\": \"4\",\n \"tabSize\": \"4\",\n \"WebkitHyphens\": \"none\",\n \"MozHyphens\": \"none\",\n \"msHyphens\": \"none\",\n \"hyphens\": \"none\"\n },\n \"pre[class*=\\\"language-\\\"]::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"code[class*=\\\"language-\\\"]::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"pre[class*=\\\"language-\\\"] *::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \"code[class*=\\\"language-\\\"] *::selection\": {\n \"textShadow\": \"none\",\n \"background\": \"#264F78\"\n },\n \":not(pre) > code[class*=\\\"language-\\\"]\": {\n \"padding\": \".1em .3em\",\n \"borderRadius\": \".3em\",\n \"color\": \"#db4c69\",\n \"background\": \"#1e1e1e\"\n },\n \".namespace\": {\n \"Opacity\": \".7\"\n },\n \"doctype.doctype-tag\": {\n \"color\": \"#569CD6\"\n },\n \"doctype.name\": {\n \"color\": \"#9cdcfe\"\n },\n \"comment\": {\n \"color\": \"#6a9955\"\n },\n \"prolog\": {\n \"color\": \"#6a9955\"\n },\n \"punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-html .language-css .token.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-html .language-javascript .token.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \"property\": {\n \"color\": \"#9cdcfe\"\n },\n \"tag\": {\n \"color\": \"#569cd6\"\n },\n \"boolean\": {\n \"color\": \"#569cd6\"\n },\n \"number\": {\n \"color\": \"#b5cea8\"\n },\n \"constant\": {\n \"color\": \"#9cdcfe\"\n },\n \"symbol\": {\n \"color\": \"#b5cea8\"\n },\n \"inserted\": {\n \"color\": \"#b5cea8\"\n },\n \"unit\": {\n \"color\": \"#b5cea8\"\n },\n \"selector\": {\n \"color\": \"#d7ba7d\"\n },\n \"attr-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"string\": {\n \"color\": \"#ce9178\"\n },\n \"char\": {\n \"color\": \"#ce9178\"\n },\n \"builtin\": {\n \"color\": \"#ce9178\"\n },\n \"deleted\": {\n \"color\": \"#ce9178\"\n },\n \".language-css .token.string.url\": {\n \"textDecoration\": \"underline\"\n },\n \"operator\": {\n \"color\": \"#d4d4d4\"\n },\n \"entity\": {\n \"color\": \"#569cd6\"\n },\n \"operator.arrow\": {\n \"color\": \"#569CD6\"\n },\n \"atrule\": {\n \"color\": \"#ce9178\"\n },\n \"atrule.rule\": {\n \"color\": \"#c586c0\"\n },\n \"atrule.url\": {\n \"color\": \"#9cdcfe\"\n },\n \"atrule.url.function\": {\n \"color\": \"#dcdcaa\"\n },\n \"atrule.url.punctuation\": {\n \"color\": \"#d4d4d4\"\n },\n \"keyword\": {\n \"color\": \"#569CD6\"\n },\n \"keyword.module\": {\n \"color\": \"#c586c0\"\n },\n \"keyword.control-flow\": {\n \"color\": \"#c586c0\"\n },\n \"function\": {\n \"color\": \"#dcdcaa\"\n },\n \"function.maybe-class-name\": {\n \"color\": \"#dcdcaa\"\n },\n \"regex\": {\n \"color\": \"#d16969\"\n },\n \"important\": {\n \"color\": \"#569cd6\"\n },\n \"italic\": {\n \"fontStyle\": \"italic\"\n },\n \"class-name\": {\n \"color\": \"#4ec9b0\"\n },\n \"maybe-class-name\": {\n \"color\": \"#4ec9b0\"\n },\n \"console\": {\n \"color\": \"#9cdcfe\"\n },\n \"parameter\": {\n \"color\": \"#9cdcfe\"\n },\n \"interpolation\": {\n \"color\": \"#9cdcfe\"\n },\n \"punctuation.interpolation-punctuation\": {\n \"color\": \"#569cd6\"\n },\n \"variable\": {\n \"color\": \"#9cdcfe\"\n },\n \"imports.maybe-class-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"exports.maybe-class-name\": {\n \"color\": \"#9cdcfe\"\n },\n \"escape\": {\n \"color\": \"#d7ba7d\"\n },\n \"tag.punctuation\": {\n \"color\": \"#808080\"\n },\n \"cdata\": {\n \"color\": \"#808080\"\n },\n \"attr-value\": {\n \"color\": \"#ce9178\"\n },\n \"attr-value.punctuation\": {\n \"color\": \"#ce9178\"\n },\n \"attr-value.punctuation.attr-equals\": {\n \"color\": \"#d4d4d4\"\n },\n \"namespace\": {\n \"color\": \"#4ec9b0\"\n },\n \"pre[class*=\\\"language-javascript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-javascript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-jsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-jsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-typescript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-typescript\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-tsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"code[class*=\\\"language-tsx\\\"]\": {\n \"color\": \"#9cdcfe\"\n },\n \"pre[class*=\\\"language-css\\\"]\": {\n \"color\": \"#ce9178\"\n },\n \"code[class*=\\\"language-css\\\"]\": {\n \"color\": \"#ce9178\"\n },\n \"pre[class*=\\\"language-html\\\"]\": {\n \"color\": \"#d4d4d4\"\n },\n \"code[class*=\\\"language-html\\\"]\": {\n \"color\": \"#d4d4d4\"\n },\n \".language-regex .token.anchor\": {\n \"color\": \"#dcdcaa\"\n },\n \".language-html .token.punctuation\": {\n \"color\": \"#808080\"\n },\n \"pre[class*=\\\"language-\\\"] > code[class*=\\\"language-\\\"]\": {\n \"position\": \"relative\",\n \"zIndex\": \"1\"\n },\n \".line-highlight.line-highlight\": {\n \"background\": \"#f7ebc6\",\n \"boxShadow\": \"inset 5px 0 0 #f7d87c\",\n \"zIndex\": \"0\"\n }\n};","import { useState, useEffect } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\n\ninterface MarkdownRendererProps {\n url: string;\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ url }) => {\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadMarkdown = async () => {\n try {\n setLoading(true);\n setError(null);\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('加载失败');\n }\n const text = await response.text();\n setContent(text);\n } catch (err) {\n setError('Markdown 文件加载失败');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadMarkdown();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-4 md:p-8\">\n <div className=\"max-w-full md:max-w-4xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl p-4 md:p-8 border border-white/10\">\n <div className=\"prose prose-invert prose-sm md:prose-lg max-w-none\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code({ node, inline, className, children, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '');\n return !inline && match ? (\n <SyntaxHighlighter\n style={vscDarkPlus}\n language={match[1]}\n PreTag=\"div\"\n className=\"rounded-lg\"\n {...props}\n >\n {String(children).replace(/\\n$/, '')}\n </SyntaxHighlighter>\n ) : (\n <code className=\"bg-white/10 px-1.5 py-0.5 rounded text-sm\" {...props}>\n {children}\n </code>\n );\n },\n h1: ({ children }) => (\n <h1 className=\"text-4xl font-bold mb-4 text-white border-b border-white/20 pb-2\">\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2 className=\"text-3xl font-bold mb-3 text-white mt-8\">{children}</h2>\n ),\n h3: ({ children }) => (\n <h3 className=\"text-2xl font-bold mb-2 text-white mt-6\">{children}</h3>\n ),\n p: ({ children }) => <p className=\"text-white/90 mb-4 leading-relaxed\">{children}</p>,\n a: ({ href, children }) => (\n <a\n href={href}\n className=\"text-blue-400 hover:text-blue-300 underline\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </a>\n ),\n ul: ({ children }) => <ul className=\"list-disc list-inside mb-4 text-white/90\">{children}</ul>,\n ol: ({ children }) => <ol className=\"list-decimal list-inside mb-4 text-white/90\">{children}</ol>,\n li: ({ children }) => <li className=\"mb-1\">{children}</li>,\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-4 border-blue-500 pl-4 italic text-white/80 my-4\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-4\">\n <table className=\"min-w-full border border-white/20\">{children}</table>\n </div>\n ),\n th: ({ children }) => (\n <th className=\"border border-white/20 px-4 py-2 bg-white/10 text-white font-semibold\">\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className=\"border border-white/20 px-4 py-2 text-white/90\">{children}</td>\n ),\n hr: () => <hr className=\"border-white/20 my-6\" />,\n img: ({ src, alt }) => (\n <img src={src} alt={alt} className=\"rounded-lg max-w-full h-auto my-4\" />\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n </div>\n </div>\n );\n};\n\n","import { useState, useEffect } from 'react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport { FileText } from 'lucide-react';\n\ninterface TextRendererProps {\n url: string;\n fileName: string;\n}\n\nconst getLanguageFromFileName = (fileName: string): string => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n const languageMap: Record<string, string> = {\n js: 'javascript',\n jsx: 'jsx',\n ts: 'typescript',\n tsx: 'tsx',\n py: 'python',\n java: 'java',\n cpp: 'cpp',\n c: 'c',\n cs: 'csharp',\n php: 'php',\n rb: 'ruby',\n go: 'go',\n rs: 'rust',\n swift: 'swift',\n kt: 'kotlin',\n scala: 'scala',\n sh: 'bash',\n bash: 'bash',\n zsh: 'bash',\n json: 'json',\n xml: 'xml',\n html: 'html',\n css: 'css',\n scss: 'scss',\n sass: 'sass',\n less: 'less',\n sql: 'sql',\n yaml: 'yaml',\n yml: 'yaml',\n toml: 'toml',\n ini: 'ini',\n conf: 'nginx',\n md: 'markdown',\n txt: 'text',\n };\n return languageMap[ext] || 'text';\n};\n\nexport const TextRenderer: React.FC<TextRendererProps> = ({ url, fileName }) => {\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const language = getLanguageFromFileName(fileName);\n\n useEffect(() => {\n const loadText = async () => {\n try {\n setLoading(true);\n setError(null);\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error('加载失败');\n }\n const text = await response.text();\n setContent(text);\n } catch (err) {\n setError('文本文件加载失败');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n loadText();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"w-12 h-12 border-4 border-white/20 border-t-white rounded-full animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center w-full h-full\">\n <div className=\"text-white/70 text-center\">\n <p className=\"text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"w-full h-full overflow-auto p-4 md:p-8\">\n <div className=\"max-w-full md:max-w-6xl mx-auto bg-white/5 backdrop-blur-sm rounded-2xl border border-white/10 overflow-hidden\">\n {/* 文件头部 */}\n <div className=\"flex items-center gap-2 md:gap-3 px-4 py-3 md:px-6 md:py-4 bg-white/5 border-b border-white/10\">\n <FileText className=\"w-4 h-4 md:w-5 md:h-5 text-white/70 flex-shrink-0\" />\n <span className=\"text-white font-medium text-sm md:text-base truncate\">{fileName}</span>\n <span className=\"ml-auto text-xs text-white/50 uppercase flex-shrink-0\">{language}</span>\n </div>\n\n {/* 代码内容 */}\n <div className=\"text-sm\">\n {language === 'text' ? (\n <pre className=\"p-6 text-white/90 font-mono whitespace-pre-wrap break-words\">\n {content}\n </pre>\n ) : (\n <SyntaxHighlighter\n language={language}\n style={vscDarkPlus}\n showLineNumbers\n customStyle={{\n margin: 0,\n padding: '1.5rem',\n background: 'transparent',\n fontSize: '0.875rem',\n }}\n lineNumberStyle={{\n minWidth: '3em',\n paddingRight: '1em',\n color: 'rgba(255, 255, 255, 0.3)',\n userSelect: 'none',\n }}\n >\n {content}\n </SyntaxHighlighter>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n","import { FileQuestion, Download } from 'lucide-react';\n\ninterface UnsupportedRendererProps {\n fileName: string;\n fileType: string;\n onDownload: () => void;\n}\n\nexport const UnsupportedRenderer: React.FC<UnsupportedRendererProps> = ({\n fileName,\n fileType,\n onDownload,\n}) => {\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-8 gap-6\">\n <div className=\"w-32 h-32 rounded-full bg-white/10 flex items-center justify-center\">\n <FileQuestion className=\"w-16 h-16 text-white/70\" />\n </div>\n\n <div className=\"text-white text-center\">\n <p className=\"text-xl font-medium mb-2\">{fileName}</p>\n <p className=\"text-white/70\">不支持预览此文件类型 ({fileType})</p>\n </div>\n\n <button\n onClick={onDownload}\n 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\"\n >\n <Download className=\"w-5 h-5\" />\n 下载文件查看\n </button>\n </div>\n );\n};\n\n","import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n X,\n ZoomIn,\n ZoomOut,\n RotateCw,\n RotateCcw,\n Download,\n ChevronLeft,\n ChevronRight,\n Maximize2,\n Minimize2,\n RefreshCw,\n} from 'lucide-react';\nimport { PreviewFile, PreviewFileInput, FileType, CustomRenderer } from './types';\nimport { normalizeFiles } from './utils/fileNormalizer';\nimport { ImageRenderer } from './renderers/ImageRenderer';\nimport { PdfRenderer } from './renderers/PdfRenderer';\nimport { DocxRenderer } from './renderers/DocxRenderer';\nimport { XlsxRenderer } from './renderers/XlsxRenderer';\nimport { PptxRenderer } from './renderers/PptxRenderer';\nimport { VideoRenderer } from './renderers/VideoRenderer';\nimport { AudioRenderer } from './renderers/AudioRenderer';\nimport { MarkdownRenderer } from './renderers/MarkdownRenderer';\nimport { TextRenderer } from './renderers/TextRenderer';\nimport { UnsupportedRenderer } from './renderers/UnsupportedRenderer';\n\ninterface FilePreviewModalProps {\n files: PreviewFileInput[];\n currentIndex: number;\n isOpen: boolean;\n onClose: () => void;\n onNavigate?: (index: number) => void;\n customRenderers?: CustomRenderer[];\n}\n\nconst getFileType = (file: PreviewFile): FileType => {\n const ext = file.name.split('.').pop()?.toLowerCase() || '';\n const mimeType = file.type.toLowerCase();\n\n if (mimeType.startsWith('image/') || ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(ext)) {\n return 'image';\n }\n if (mimeType.includes('pdf') || ext === 'pdf') {\n return 'pdf';\n }\n if (mimeType.includes('wordprocessingml') || ext === 'docx') {\n return 'docx';\n }\n if (mimeType.includes('spreadsheetml') || ext === 'xlsx') {\n return 'xlsx';\n }\n if (mimeType.includes('presentationml') || ext === 'pptx' || ext === 'ppt') {\n return 'pptx';\n }\n if (mimeType.startsWith('video/') || ['mp4', 'webm', 'ogg', 'ogv', 'mov', 'avi', 'mkv', 'm4v', '3gp', 'flv'].includes(ext)) {\n return 'video';\n }\n if (mimeType.startsWith('audio/') || ['mp3', 'wav', 'ogg', 'm4a', 'flac', 'aac'].includes(ext)) {\n return 'audio';\n }\n if (ext === 'md' || ext === 'markdown') {\n return 'markdown';\n }\n // 文本文件和代码文件\n const textExtensions = [\n 'txt', 'log', 'csv',\n 'js', 'jsx', 'ts', 'tsx', 'json',\n 'py', 'java', 'cpp', 'c', 'h', 'cs', 'php', 'rb', 'go', 'rs', 'swift', 'kt',\n 'html', 'css', 'scss', 'sass', 'less',\n 'xml', 'yaml', 'yml', 'toml', 'ini', 'conf',\n 'sh', 'bash', 'zsh', 'sql',\n ];\n if (mimeType.startsWith('text/') || textExtensions.includes(ext)) {\n return 'text';\n }\n return 'unsupported';\n};\n\nexport const FilePreviewModal: React.FC<FilePreviewModalProps> = ({\n files,\n currentIndex,\n isOpen,\n onClose,\n onNavigate,\n customRenderers = [],\n}) => {\n const [zoom, setZoom] = useState(1);\n const [rotation, setRotation] = useState(0);\n const [currentPage, setCurrentPage] = useState(1);\n const [, setTotalPages] = useState(1); // PDF 总页数,由 PdfRenderer 更新\n\n // 滑动手势状态\n const [touchStart, setTouchStart] = useState<number | null>(null);\n const [touchEnd, setTouchEnd] = useState<number | null>(null);\n const minSwipeDistance = 50;\n\n // 标准化文件输入\n const normalizedFiles = useMemo(() => normalizeFiles(files), [files]);\n\n const currentFile = normalizedFiles[currentIndex];\n\n // 检查是否有自定义渲染器匹配当前文件\n const customRenderer = useMemo(() => {\n if (!currentFile) return null;\n return customRenderers.find(renderer => renderer.test(currentFile));\n }, [currentFile, customRenderers]);\n\n const fileType = currentFile ? getFileType(currentFile) : 'unsupported';\n\n // 重置状态当文件改变时\n useEffect(() => {\n setZoom(1);\n setRotation(0);\n setCurrentPage(1);\n setTotalPages(1);\n }, [currentIndex]);\n\n // 键盘导航\n // 锁定 body 滚动\n useEffect(() => {\n if (isOpen) {\n // 保存原始的 overflow 值\n const originalOverflow = document.body.style.overflow;\n const originalPaddingRight = document.body.style.paddingRight;\n\n // 获取滚动条宽度\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n // 锁定滚动并补偿滚动条宽度\n document.body.style.overflow = 'hidden';\n if (scrollbarWidth > 0) {\n document.body.style.paddingRight = `${scrollbarWidth}px`;\n }\n\n return () => {\n // 恢复原始值\n document.body.style.overflow = originalOverflow;\n document.body.style.paddingRight = originalPaddingRight;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n } else if (e.key === 'ArrowLeft' && currentIndex > 0) {\n onNavigate?.(currentIndex - 1);\n } else if (e.key === 'ArrowRight' && currentIndex < normalizedFiles.length - 1) {\n onNavigate?.(currentIndex + 1);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, currentIndex, normalizedFiles.length, onClose, onNavigate]);\n\n const handleZoomIn = useCallback(() => {\n setZoom((prev) => Math.min(prev + 0.25, 10));\n }, []);\n\n const handleZoomOut = useCallback(() => {\n setZoom((prev) => Math.max(prev - 0.25, 0.01));\n }, []);\n\n const handleRotate = useCallback(() => {\n setRotation((prev) => prev + 90);\n }, []);\n\n const handleRotateLeft = useCallback(() => {\n setRotation((prev) => prev - 90);\n }, []);\n\n const handleFitToWidth = useCallback(() => {\n setZoom(1);\n setRotation(0);\n }, []);\n\n const handleOriginalSize = useCallback(() => {\n setZoom(1);\n }, []);\n\n const handleZoomChange = useCallback((newZoom: number) => {\n setZoom(newZoom);\n }, []);\n\n const handleReset = useCallback(() => {\n setZoom(1);\n setRotation(0);\n }, []);\n\n const handleDownload = useCallback(() => {\n if (!currentFile) return;\n const link = document.createElement('a');\n link.href = currentFile.url;\n link.download = currentFile.name;\n link.click();\n }, [currentFile]);\n\n // 滑动手势处理\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n setTouchEnd(null);\n setTouchStart(e.targetTouches[0].clientX);\n }, []);\n\n const handleTouchMove = useCallback((e: React.TouchEvent) => {\n setTouchEnd(e.targetTouches[0].clientX);\n }, []);\n\n const handleTouchEnd = useCallback(() => {\n if (!touchStart || !touchEnd) return;\n const distance = touchStart - touchEnd;\n const isLeftSwipe = distance > minSwipeDistance;\n const isRightSwipe = distance < -minSwipeDistance;\n\n if (isLeftSwipe && currentIndex < normalizedFiles.length - 1) {\n onNavigate?.(currentIndex + 1);\n }\n if (isRightSwipe && currentIndex > 0) {\n onNavigate?.(currentIndex - 1);\n }\n }, [touchStart, touchEnd, minSwipeDistance, currentIndex, normalizedFiles.length, onNavigate]);\n\n if (!isOpen || !currentFile) return null;\n\n const showZoomControls = fileType === 'image' || fileType === 'pdf';\n const showRotateControl = fileType === 'image';\n\n const modalContent = (\n <AnimatePresence>\n {isOpen && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-md overflow-hidden\"\n onClick={onClose}\n onWheel={(e) => e.stopPropagation()}\n >\n {/* 主内容区域 */}\n <div\n className=\"relative w-full h-full flex flex-col overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 顶部工具栏 */}\n <motion.div\n initial={{ y: -100 }}\n animate={{ y: 0 }}\n exit={{ y: -100 }}\n className=\"absolute top-0 left-0 right-0 z-10 p-4\"\n >\n <div className=\"max-w-7xl mx-auto flex flex-col md:flex-row md:items-center md:justify-between bg-black/40 backdrop-blur-xl rounded-2xl px-3 md:px-6 py-3 md:py-4 shadow-2xl border border-white/10 gap-2 md:gap-0\">\n {/* 第一行:文件名 + 关闭按钮(移动端) */}\n <div className=\"flex items-center justify-between md:flex-1 md:min-w-0 md:mr-4\">\n <div className=\"flex-1 min-w-0\">\n <h2 className=\"text-white font-medium text-sm md:text-lg truncate\">\n {currentFile.name}\n </h2>\n <p className=\"text-white/60 text-xs md:text-sm\">\n {currentIndex + 1} / {normalizedFiles.length}\n </p>\n </div>\n {/* 移动端关闭按钮 */}\n <div className=\"md:hidden ml-2\">\n <ToolbarButton\n icon={<X className=\"w-5 h-5\" />}\n label=\"关闭\"\n onClick={onClose}\n />\n </div>\n </div>\n\n {/* 第二行:工具按钮 - 支持水平滚动 */}\n <div className=\"flex items-center gap-1 md:gap-2 overflow-x-auto scrollbar-hide flex-shrink-0\">\n {showZoomControls && (\n <>\n <ToolbarButton\n icon={<ZoomOut className=\"w-5 h-5\" />}\n label=\"缩小\"\n onClick={handleZoomOut}\n disabled={zoom <= 0.01}\n />\n <span className=\"text-white/70 text-sm min-w-[4rem] text-center font-medium\">\n {Math.round(zoom * 100)}%\n </span>\n <ToolbarButton\n icon={<ZoomIn className=\"w-5 h-5\" />}\n label=\"放大\"\n onClick={handleZoomIn}\n disabled={zoom >= 10}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n <ToolbarButton\n icon={<Minimize2 className=\"w-5 h-5\" />}\n label=\"适应窗口\"\n onClick={handleFitToWidth}\n />\n <ToolbarButton\n icon={<Maximize2 className=\"w-5 h-5\" />}\n label=\"原始尺寸\"\n onClick={handleOriginalSize}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n {showRotateControl && (\n <>\n <ToolbarButton\n icon={<RotateCcw className=\"w-5 h-5\" />}\n label=\"向左旋转\"\n onClick={handleRotateLeft}\n />\n <ToolbarButton\n icon={<RotateCw className=\"w-5 h-5\" />}\n label=\"向右旋转\"\n onClick={handleRotate}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n {(showZoomControls || showRotateControl) && (\n <>\n <ToolbarButton\n icon={<RefreshCw className=\"w-5 h-5\" />}\n label=\"复原\"\n onClick={handleReset}\n />\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n </>\n )}\n\n <ToolbarButton\n icon={<Download className=\"w-5 h-5\" />}\n label=\"下载\"\n onClick={handleDownload}\n />\n\n {/* 桌面端关闭按钮 */}\n <div className=\"hidden md:flex items-center\">\n <div className=\"w-px h-6 bg-white/20 mx-2\" />\n <ToolbarButton\n icon={<X className=\"w-5 h-5\" />}\n label=\"关闭\"\n onClick={onClose}\n />\n </div>\n </div>\n </div>\n </motion.div>\n\n {/* 内容区域 */}\n <div\n className=\"flex-1 flex items-center justify-center pt-32 md:pt-24 pb-4 md:pb-8 overflow-auto\"\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n {customRenderer ? (\n // 使用自定义渲染器\n customRenderer.render(currentFile)\n ) : (\n <>\n {fileType === 'image' && (\n <ImageRenderer\n url={currentFile.url}\n zoom={zoom}\n rotation={rotation}\n onZoomChange={handleZoomChange}\n />\n )}\n {fileType === 'pdf' && (\n <PdfRenderer\n url={currentFile.url}\n zoom={zoom}\n currentPage={currentPage}\n onPageChange={setCurrentPage}\n onTotalPagesChange={setTotalPages}\n />\n )}\n {fileType === 'docx' && <DocxRenderer url={currentFile.url} />}\n {fileType === 'xlsx' && <XlsxRenderer url={currentFile.url} />}\n {fileType === 'pptx' && <PptxRenderer url={currentFile.url} />}\n {fileType === 'video' && <VideoRenderer url={currentFile.url} />}\n {fileType === 'audio' && (\n <AudioRenderer url={currentFile.url} fileName={currentFile.name} />\n )}\n {fileType === 'markdown' && <MarkdownRenderer url={currentFile.url} />}\n {fileType === 'text' && (\n <TextRenderer url={currentFile.url} fileName={currentFile.name} />\n )}\n {fileType === 'unsupported' && (\n <UnsupportedRenderer\n fileName={currentFile.name}\n fileType={currentFile.type}\n onDownload={handleDownload}\n />\n )}\n </>\n )}\n </div>\n\n {/* 左右导航箭头 */}\n {normalizedFiles.length > 1 && (\n <>\n {currentIndex > 0 && (\n <motion.button\n initial={{ x: -100, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n exit={{ x: -100, opacity: 0 }}\n onClick={() => onNavigate?.(currentIndex - 1)}\n className=\"absolute left-2 md:left-4 top-1/2 -translate-y-1/2 w-10 h-10 md:w-12 md: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\"\n >\n <ChevronLeft className=\"w-5 h-5 md:w-6 md:h-6\" />\n </motion.button>\n )}\n\n {currentIndex < normalizedFiles.length - 1 && (\n <motion.button\n initial={{ x: 100, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n exit={{ x: 100, opacity: 0 }}\n onClick={() => onNavigate?.(currentIndex + 1)}\n className=\"absolute right-2 md:right-4 top-1/2 -translate-y-1/2 w-10 h-10 md:w-12 md: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\"\n >\n <ChevronRight className=\"w-5 h-5 md:w-6 md:h-6\" />\n </motion.button>\n )}\n </>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n );\n\n // 使用 Portal 将模态框渲染到 document.body\n return createPortal(modalContent, document.body);\n};\n\n// 工具栏按钮组件\ninterface ToolbarButtonProps {\n icon: React.ReactNode;\n label: string;\n onClick: () => void;\n disabled?: boolean;\n}\n\nconst ToolbarButton: React.FC<ToolbarButtonProps> = ({ icon, label, onClick, disabled }) => {\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n title={label}\n className={`p-2 rounded-lg transition-all ${disabled\n ? 'text-white/30 cursor-not-allowed'\n : 'text-white hover:bg-white/10 active:bg-white/20'\n }`}\n >\n {icon}\n </button>\n );\n};\n\n","// 导入样式\nimport './index.css';\n\n// 导入版本号\nimport packageJson from '../package.json';\n\n// 导出版本号\nexport const VERSION = packageJson.version;\n\n// 导出主组件\nexport { FilePreviewModal } from './FilePreviewModal';\n\n// 导出类型定义\nexport type {\n PreviewFile,\n PreviewFileLink,\n PreviewFileInput,\n FileType,\n ToolbarAction,\n PreviewState,\n CustomRenderer,\n} from './types';\n\n// 导出工具函数\nexport { normalizeFile, normalizeFiles } from './utils/fileNormalizer';\n\n// 导出 PDF.js 配置函数和类型\nexport { configurePdfjs, pdfjs } from './utils/pdfConfig';\nexport type { PdfConfigOptions } from './utils/pdfConfig';\n\n"],"names":["getFileNameFromUrl","url","fileName","inferMimeType","ext","_a","normalizeFile","input","index","normalizeFiles","inputs","ImageRenderer","zoom","rotation","onZoomChange","loaded","setLoaded","useState","error","setError","position","setPosition","isDragging","setIsDragging","dragStart","setDragStart","internalZoom","setInternalZoom","containerRef","useRef","useEffect","handleLoad","handleError","handleDoubleClick","handleWheel","useCallback","e","delta","prev","newZoom","handleMouseDown","handleMouseMove","handleMouseUp","jsxs","jsx","motion","configurePdfjs","options","workerSrc","pdfjs","cMapUrl","cMapPacked","PdfRenderer","currentPage","onPageChange","onTotalPagesChange","numPages","setNumPages","pageRefs","onDocumentLoadSuccess","onDocumentLoadError","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","pageElement","pageNumber","rect","containerRect","pageCenter","distance","setPageRef","element","Document","_","el","Page","DocxRenderer","html","setHtml","loading","setLoading","response","arrayBuffer","result","mammoth","err","XlsxRenderer","sheets","setSheets","activeSheet","setActiveSheet","workbook","XLSX","parsedSheets","name","worksheet","data","currentSheet","sheet","row","rowIndex","cell","cellIndex","PptxRenderer","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","isInitialRender","updateDimensions","initialDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadPptx","previewErr","timer","Presentation","getVideoType","VideoRenderer","isLoading","setIsLoading","videoRef","playerRef","videoElement","videoType","player","videojs","AudioRenderer","isPlaying","setIsPlaying","currentTime","setCurrentTime","duration","setDuration","volume","setVolume","isMuted","setIsMuted","audioRef","audio","updateTime","updateDuration","handleEnded","handleCanPlay","togglePlay","handleSeek","time","handleVolumeChange","vol","toggleMute","skip","seconds","formatTime","minutes","Music","SkipBack","Pause","Play","SkipForward","VolumeX","Volume2","vscDarkPlus","MarkdownRenderer","content","setContent","text","ReactMarkdown","remarkGfm","node","inline","className","children","props","match","SyntaxHighlighter","href","src","alt","getLanguageFromFileName","TextRenderer","language","FileText","UnsupportedRenderer","fileType","onDownload","FileQuestion","Download","getFileType","file","mimeType","textExtensions","FilePreviewModal","files","currentIndex","isOpen","onClose","onNavigate","customRenderers","setZoom","setRotation","setCurrentPage","setTotalPages","touchStart","setTouchStart","touchEnd","setTouchEnd","minSwipeDistance","normalizedFiles","useMemo","currentFile","customRenderer","renderer","originalOverflow","originalPaddingRight","scrollbarWidth","handleKeyDown","handleZoomIn","handleZoomOut","handleRotate","handleRotateLeft","handleFitToWidth","handleOriginalSize","handleZoomChange","handleReset","handleDownload","link","handleTouchStart","handleTouchMove","handleTouchEnd","isLeftSwipe","isRightSwipe","showZoomControls","showRotateControl","modalContent","AnimatePresence","ToolbarButton","X","Fragment","ZoomOut","ZoomIn","Minimize2","Maximize2","RotateCcw","RotateCw","RefreshCw","ChevronLeft","ChevronRight","createPortal","icon","label","onClick","disabled","VERSION","packageJson"],"mappings":"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U,QAAA,CAAA,CACZ,EACF,CAEJ,EClOAgJ,EAAe,CACb,0BAA6B,CAC3B,MAAS,UACT,SAAY,OACZ,WAAc,OACd,WAAc,kFACd,UAAa,MACb,UAAa,OACb,WAAc,MACd,YAAe,SACf,UAAa,SACb,WAAc,MACd,WAAc,IACd,SAAY,IACZ,QAAW,IACX,cAAiB,OACjB,WAAc,OACd,UAAa,OACb,QAAW,OACX,QAAW,MACX,OAAU,SACV,SAAY,OACZ,WAAc,SAClB,EACE,2BAA8B,CAC5B,MAAS,UACT,SAAY,OACZ,WAAc,OACd,WAAc,kFACd,UAAa,MACb,UAAa,OACb,WAAc,MACd,YAAe,SACf,UAAa,SACb,WAAc,MACd,WAAc,IACd,SAAY,IACZ,QAAW,IACX,cAAiB,OACjB,WAAc,OACd,UAAa,OACb,QAAW,MACf,EACE,qCAAwC,CACtC,WAAc,OACd,WAAc,SAClB,EACE,sCAAyC,CACvC,WAAc,OACd,WAAc,SAClB,EACE,uCAA0C,CACxC,WAAc,OACd,WAAc,SAClB,EACE,wCAA2C,CACzC,WAAc,OACd,WAAc,SAClB,EACE,uCAA0C,CACxC,QAAW,YACX,aAAgB,OAChB,MAAS,UACT,WAAc,SAClB,EACE,aAAc,CACZ,QAAW,IACf,EACE,sBAAuB,CACrB,MAAS,SACb,EACE,eAAgB,CACd,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,YAAe,CACb,MAAS,SACb,EACE,kDAAmD,CACjD,MAAS,SACb,EACE,yDAA0D,CACxD,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,IAAO,CACL,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,KAAQ,CACN,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,YAAa,CACX,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,KAAQ,CACN,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,kCAAmC,CACjC,eAAkB,WACtB,EACE,SAAY,CACV,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,iBAAkB,CAChB,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,cAAe,CACb,MAAS,SACb,EACE,aAAc,CACZ,MAAS,SACb,EACE,sBAAuB,CACrB,MAAS,SACb,EACE,yBAA0B,CACxB,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,iBAAkB,CAChB,MAAS,SACb,EACE,uBAAwB,CACtB,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,4BAA6B,CAC3B,MAAS,SACb,EACE,MAAS,CACP,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,OAAU,CACR,UAAa,QACjB,EACE,aAAc,CACZ,MAAS,SACb,EACE,mBAAoB,CAClB,MAAS,SACb,EACE,QAAW,CACT,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,cAAiB,CACf,MAAS,SACb,EACE,wCAAyC,CACvC,MAAS,SACb,EACE,SAAY,CACV,MAAS,SACb,EACE,2BAA4B,CAC1B,MAAS,SACb,EACE,2BAA4B,CAC1B,MAAS,SACb,EACE,OAAU,CACR,MAAS,SACb,EACE,kBAAmB,CACjB,MAAS,SACb,EACE,MAAS,CACP,MAAS,SACb,EACE,aAAc,CACZ,MAAS,SACb,EACE,yBAA0B,CACxB,MAAS,SACb,EACE,qCAAsC,CACpC,MAAS,SACb,EACE,UAAa,CACX,MAAS,SACb,EACE,oCAAuC,CACrC,MAAS,SACb,EACE,qCAAwC,CACtC,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,oCAAuC,CACrC,MAAS,SACb,EACE,qCAAwC,CACtC,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,6BAAgC,CAC9B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,8BAAiC,CAC/B,MAAS,SACb,EACE,+BAAkC,CAChC,MAAS,SACb,EACE,gCAAiC,CAC/B,MAAS,SACb,EACE,oCAAqC,CACnC,MAAS,SACb,EACE,qDAA0D,CACxD,SAAY,WACZ,OAAU,GACd,EACE,iCAAkC,CAChC,WAAc,UACd,UAAa,wBACb,OAAU,GACd,CACA,EC/QaC,GAAoD,CAAC,CAAE,IAAAhL,KAAU,CAC5E,KAAM,CAACiL,EAASC,CAAU,EAAIlK,EAAAA,SAAiB,EAAE,EAC3C,CAACkE,EAASC,CAAU,EAAInE,EAAAA,SAAS,EAAI,EACrC,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAAwB,IAAI,EAwBtD,OAtBAa,EAAAA,UAAU,IAAM,EACO,SAAY,CAC/B,GAAI,CACFsD,EAAW,EAAI,EACfjE,EAAS,IAAI,EACb,MAAMkE,EAAW,MAAM,MAAMpF,CAAG,EAChC,GAAI,CAACoF,EAAS,GACZ,MAAM,IAAI,MAAM,MAAM,EAExB,MAAM+F,EAAO,MAAM/F,EAAS,KAAA,EAC5B8F,EAAWC,CAAI,CACjB,OAAS3F,EAAK,CACZtE,EAAS,iBAAiB,EAC1B,QAAQ,MAAMsE,CAAG,CACnB,QAAA,CACEL,EAAW,EAAK,CAClB,CACF,GAEA,CACF,EAAG,CAACnF,CAAG,CAAC,EAEJkF,EAEAvC,MAAC,OAAI,UAAU,iDACb,eAAC,MAAA,CAAI,UAAU,8EAA8E,CAAA,CAC/F,EAIA1B,EAEA0B,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACb,eAAC,MAAA,CAAI,UAAU,4BACb,SAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,UAAW,SAAA1B,CAAA,CAAM,EAChC,EACF,EAKF0B,EAAAA,IAAC,MAAA,CAAI,UAAU,yCACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,4GACb,SAAAA,MAAC,MAAA,CAAI,UAAU,qDACb,SAAAA,EAAAA,IAACyI,GAAA,CACC,cAAe,CAACC,EAAS,EACzB,WAAY,CACV,KAAK,CAAE,KAAAC,EAAM,OAAAC,EAAQ,UAAAC,EAAW,SAAAC,EAAU,GAAGC,GAAc,CACzD,MAAMC,EAAQ,iBAAiB,KAAKH,GAAa,EAAE,EACnD,MAAO,CAACD,GAAUI,EAChBhJ,EAAAA,IAACiJ,EAAAA,MAAA,CACC,MAAOb,EACP,SAAUY,EAAM,CAAC,EACjB,OAAO,MACP,UAAU,aACT,GAAGD,EAEH,SAAA,OAAOD,CAAQ,EAAE,QAAQ,MAAO,EAAE,CAAA,CAAA,EAGrC9I,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA6C,GAAG+I,EAC7D,SAAAD,EACH,CAEJ,EACA,GAAI,CAAC,CAAE,SAAAA,CAAA,IACL9I,EAAAA,IAAC,KAAA,CAAG,UAAU,mEACX,SAAA8I,EACH,EAEF,GAAI,CAAC,CAAE,SAAAA,CAAA,IACL9I,EAAAA,IAAC,KAAA,CAAG,UAAU,0CAA2C,SAAA8I,EAAS,EAEpE,GAAI,CAAC,CAAE,SAAAA,CAAA,IACL9I,EAAAA,IAAC,KAAA,CAAG,UAAU,0CAA2C,SAAA8I,EAAS,EAEpE,EAAG,CAAC,CAAE,SAAAA,CAAA,IAAe9I,EAAAA,IAAC,IAAA,CAAE,UAAU,qCAAsC,SAAA8I,EAAS,EACjF,EAAG,CAAC,CAAE,KAAAI,EAAM,SAAAJ,KACV9I,EAAAA,IAAC,IAAA,CACC,KAAAkJ,EACA,UAAU,8CACV,OAAO,SACP,IAAI,sBAEH,SAAAJ,CAAA,CAAA,EAGL,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAe9I,EAAAA,IAAC,KAAA,CAAG,UAAU,2CAA4C,SAAA8I,EAAS,EACzF,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAe9I,EAAAA,IAAC,KAAA,CAAG,UAAU,8CAA+C,SAAA8I,EAAS,EAC5F,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAe9I,EAAAA,IAAC,KAAA,CAAG,UAAU,OAAQ,SAAA8I,EAAS,EACrD,WAAY,CAAC,CAAE,SAAAA,CAAA,IACb9I,EAAAA,IAAC,aAAA,CAAW,UAAU,4DACnB,SAAA8I,EACH,EAEF,MAAO,CAAC,CAAE,SAAAA,CAAA,IACR9I,EAAAA,IAAC,MAAA,CAAI,UAAU,uBACb,SAAAA,EAAAA,IAAC,QAAA,CAAM,UAAU,oCAAqC,SAAA8I,EAAS,EACjE,EAEF,GAAI,CAAC,CAAE,SAAAA,CAAA,IACL9I,EAAAA,IAAC,KAAA,CAAG,UAAU,wEACX,SAAA8I,EACH,EAEF,GAAI,CAAC,CAAE,SAAAA,CAAA,IACL9I,EAAAA,IAAC,KAAA,CAAG,UAAU,iDAAkD,SAAA8I,EAAS,EAE3E,GAAI,IAAM9I,EAAAA,IAAC,KAAA,CAAG,UAAU,sBAAA,CAAuB,EAC/C,IAAK,CAAC,CAAE,IAAAmJ,EAAK,IAAAC,KACXpJ,EAAAA,IAAC,MAAA,CAAI,IAAAmJ,EAAU,IAAAC,EAAU,UAAU,mCAAA,CAAoC,CAAA,EAI1E,SAAAd,CAAA,CAAA,CACH,CACF,EACF,EACF,CAEJ,EC7HMe,GAA2B/L,GAA6B,OAC5D,MAAME,IAAMC,EAAAH,EAAS,MAAM,GAAG,EAAE,IAAA,IAApB,YAAAG,EAA2B,gBAAiB,GAqCxD,MApC4C,CAC1C,GAAI,aACJ,IAAK,MACL,GAAI,aACJ,IAAK,MACL,GAAI,SACJ,KAAM,OACN,IAAK,MACL,EAAG,IACH,GAAI,SACJ,IAAK,MACL,GAAI,OACJ,GAAI,KACJ,GAAI,OACJ,MAAO,QACP,GAAI,SACJ,MAAO,QACP,GAAI,OACJ,KAAM,OACN,IAAK,OACL,KAAM,OACN,IAAK,MACL,KAAM,OACN,IAAK,MACL,KAAM,OACN,KAAM,OACN,KAAM,OACN,IAAK,MACL,KAAM,OACN,IAAK,OACL,KAAM,OACN,IAAK,MACL,KAAM,QACN,GAAI,WACJ,IAAK,MAAA,EAEYD,CAAG,GAAK,MAC7B,EAEa8L,GAA4C,CAAC,CAAE,IAAAjM,EAAK,SAAAC,KAAe,CAC9E,KAAM,CAACgL,EAASC,CAAU,EAAIlK,EAAAA,SAAiB,EAAE,EAC3C,CAACkE,EAASC,CAAU,EAAInE,EAAAA,SAAS,EAAI,EACrC,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAAwB,IAAI,EAChDkL,EAAWF,GAAwB/L,CAAQ,EAwBjD,OAtBA4B,EAAAA,UAAU,IAAM,EACG,SAAY,CAC3B,GAAI,CACFsD,EAAW,EAAI,EACfjE,EAAS,IAAI,EACb,MAAMkE,EAAW,MAAM,MAAMpF,CAAG,EAChC,GAAI,CAACoF,EAAS,GACZ,MAAM,IAAI,MAAM,MAAM,EAExB,MAAM+F,EAAO,MAAM/F,EAAS,KAAA,EAC5B8F,EAAWC,CAAI,CACjB,OAAS3F,EAAK,CACZtE,EAAS,UAAU,EACnB,QAAQ,MAAMsE,CAAG,CACnB,QAAA,CACEL,EAAW,EAAK,CAClB,CACF,GAEA,CACF,EAAG,CAACnF,CAAG,CAAC,EAEJkF,EAEAvC,MAAC,OAAI,UAAU,iDACb,eAAC,MAAA,CAAI,UAAU,8EAA8E,CAAA,CAC/F,EAIA1B,EAEA0B,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACb,eAAC,MAAA,CAAI,UAAU,4BACb,SAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,UAAW,SAAA1B,CAAA,CAAM,EAChC,EACF,QAKD,MAAA,CAAI,UAAU,yCACb,SAAAyB,EAAAA,KAAC,MAAA,CAAI,UAAU,iHAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,iGACb,SAAA,CAAAC,EAAAA,IAACwJ,EAAAA,SAAA,CAAS,UAAU,mDAAA,CAAoD,EACxExJ,EAAAA,IAAC,OAAA,CAAK,UAAU,uDAAwD,SAAA1C,EAAS,EACjF0C,EAAAA,IAAC,OAAA,CAAK,UAAU,wDAAyD,SAAAuJ,CAAA,CAAS,CAAA,EACpF,EAGAvJ,EAAAA,IAAC,MAAA,CAAI,UAAU,UACZ,SAAAuJ,IAAa,OACZvJ,EAAAA,IAAC,MAAA,CAAI,UAAU,8DACZ,SAAAsI,CAAA,CACH,EAEAtI,EAAAA,IAACiJ,EAAAA,MAAA,CACC,SAAAM,EACA,MAAOnB,EACP,gBAAe,GACf,YAAa,CACX,OAAQ,EACR,QAAS,SACT,WAAY,cACZ,SAAU,UAAA,EAEZ,gBAAiB,CACf,SAAU,MACV,aAAc,MACd,MAAO,2BACP,WAAY,MAAA,EAGb,SAAAE,CAAA,CAAA,CACH,CAEJ,CAAA,CAAA,CACF,CAAA,CACF,CAEJ,EClIamB,GAA0D,CAAC,CACtE,SAAAnM,EACA,SAAAoM,EACA,WAAAC,CACF,IAEI5J,EAAAA,KAAC,MAAA,CAAI,UAAU,oEACb,SAAA,CAAAC,EAAAA,IAAC,OAAI,UAAU,sEACb,eAAC4J,EAAAA,aAAA,CAAa,UAAU,0BAA0B,CAAA,CACpD,EAEA7J,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAC,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA4B,SAAA1C,EAAS,EAClDyC,EAAAA,KAAC,IAAA,CAAE,UAAU,gBAAgB,SAAA,CAAA,eAAa2J,EAAS,GAAA,CAAA,CAAC,CAAA,EACtD,EAEA3J,EAAAA,KAAC,SAAA,CACC,QAAS4J,EACT,UAAU,oIAEV,SAAA,CAAA3J,EAAAA,IAAC6J,EAAAA,SAAA,CAAS,UAAU,SAAA,CAAU,EAAE,QAAA,CAAA,CAAA,CAElC,EACF,ECOEC,GAAeC,GAAgC,OACnD,MAAMvM,IAAMC,EAAAsM,EAAK,KAAK,MAAM,GAAG,EAAE,IAAA,IAArB,YAAAtM,EAA4B,gBAAiB,GACnDuM,EAAWD,EAAK,KAAK,YAAA,EAE3B,GAAIC,EAAS,WAAW,QAAQ,GAAK,CAAC,MAAO,OAAQ,MAAO,MAAO,OAAQ,KAAK,EAAE,SAASxM,CAAG,EAC5F,MAAO,QAET,GAAIwM,EAAS,SAAS,KAAK,GAAKxM,IAAQ,MACtC,MAAO,MAET,GAAIwM,EAAS,SAAS,kBAAkB,GAAKxM,IAAQ,OACnD,MAAO,OAET,GAAIwM,EAAS,SAAS,eAAe,GAAKxM,IAAQ,OAChD,MAAO,OAET,GAAIwM,EAAS,SAAS,gBAAgB,GAAKxM,IAAQ,QAAUA,IAAQ,MACnE,MAAO,OAET,GAAIwM,EAAS,WAAW,QAAQ,GAAK,CAAC,MAAO,OAAQ,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,KAAK,EAAE,SAASxM,CAAG,EACvH,MAAO,QAET,GAAIwM,EAAS,WAAW,QAAQ,GAAK,CAAC,MAAO,MAAO,MAAO,MAAO,OAAQ,KAAK,EAAE,SAASxM,CAAG,EAC3F,MAAO,QAET,GAAIA,IAAQ,MAAQA,IAAQ,WAC1B,MAAO,WAGT,MAAMyM,EAAiB,CACrB,MAAO,MAAO,MACd,KAAM,MAAO,KAAM,MAAO,OAC1B,KAAM,OAAQ,MAAO,IAAK,IAAK,KAAM,MAAO,KAAM,KAAM,KAAM,QAAS,KACvE,OAAQ,MAAO,OAAQ,OAAQ,OAC/B,MAAO,OAAQ,MAAO,OAAQ,MAAO,OACrC,KAAM,OAAQ,MAAO,KAAA,EAEvB,OAAID,EAAS,WAAW,OAAO,GAAKC,EAAe,SAASzM,CAAG,EACtD,OAEF,aACT,EAEa0M,GAAoD,CAAC,CAChE,MAAAC,EACA,aAAAC,EACA,OAAAC,EACA,QAAAC,EACA,WAAAC,EACA,gBAAAC,EAAkB,CAAA,CACpB,IAAM,CACJ,KAAM,CAACxM,EAAMyM,CAAO,EAAIpM,EAAAA,SAAS,CAAC,EAC5B,CAACJ,EAAUyM,CAAW,EAAIrM,EAAAA,SAAS,CAAC,EACpC,CAACoC,EAAakK,CAAc,EAAItM,EAAAA,SAAS,CAAC,EAC1C,EAAGuM,CAAa,EAAIvM,EAAAA,SAAS,CAAC,EAG9B,CAACwM,EAAYC,CAAa,EAAIzM,EAAAA,SAAwB,IAAI,EAC1D,CAAC0M,EAAUC,CAAW,EAAI3M,EAAAA,SAAwB,IAAI,EACtD4M,EAAmB,GAGnBC,EAAkBC,EAAAA,QAAQ,IAAMtN,EAAesM,CAAK,EAAG,CAACA,CAAK,CAAC,EAE9DiB,EAAcF,EAAgBd,CAAY,EAG1CiB,EAAiBF,EAAAA,QAAQ,IACxBC,EACEZ,EAAgB,KAAKc,GAAYA,EAAS,KAAKF,CAAW,CAAC,EADzC,KAExB,CAACA,EAAaZ,CAAe,CAAC,EAE3Bd,EAAW0B,EAActB,GAAYsB,CAAW,EAAI,cAG1DlM,EAAAA,UAAU,IAAM,CACduL,EAAQ,CAAC,EACTC,EAAY,CAAC,EACbC,EAAe,CAAC,EAChBC,EAAc,CAAC,CACjB,EAAG,CAACR,CAAY,CAAC,EAIjBlL,EAAAA,UAAU,IAAM,CACd,GAAImL,EAAQ,CAEV,MAAMkB,EAAmB,SAAS,KAAK,MAAM,SACvCC,EAAuB,SAAS,KAAK,MAAM,aAG3CC,EAAiB,OAAO,WAAa,SAAS,gBAAgB,YAGpE,gBAAS,KAAK,MAAM,SAAW,SAC3BA,EAAiB,IACnB,SAAS,KAAK,MAAM,aAAe,GAAGA,CAAc,MAG/C,IAAM,CAEX,SAAS,KAAK,MAAM,SAAWF,EAC/B,SAAS,KAAK,MAAM,aAAeC,CACrC,CACF,CACF,EAAG,CAACnB,CAAM,CAAC,EAEXnL,EAAAA,UAAU,IAAM,CACd,GAAI,CAACmL,EAAQ,OAEb,MAAMqB,EAAiBlM,GAAqB,CACtCA,EAAE,MAAQ,SACZ8K,EAAA,EACS9K,EAAE,MAAQ,aAAe4K,EAAe,EACjDG,GAAA,MAAAA,EAAaH,EAAe,GACnB5K,EAAE,MAAQ,cAAgB4K,EAAec,EAAgB,OAAS,IAC3EX,GAAA,MAAAA,EAAaH,EAAe,GAEhC,EAEA,cAAO,iBAAiB,UAAWsB,CAAa,EACzC,IAAM,OAAO,oBAAoB,UAAWA,CAAa,CAClE,EAAG,CAACrB,EAAQD,EAAcc,EAAgB,OAAQZ,EAASC,CAAU,CAAC,EAEtE,MAAMoB,EAAepM,EAAAA,YAAY,IAAM,CACrCkL,EAAS/K,GAAS,KAAK,IAAIA,EAAO,IAAM,EAAE,CAAC,CAC7C,EAAG,CAAA,CAAE,EAECkM,EAAgBrM,EAAAA,YAAY,IAAM,CACtCkL,EAAS/K,GAAS,KAAK,IAAIA,EAAO,IAAM,GAAI,CAAC,CAC/C,EAAG,CAAA,CAAE,EAECmM,EAAetM,EAAAA,YAAY,IAAM,CACrCmL,EAAahL,GAASA,EAAO,EAAE,CACjC,EAAG,CAAA,CAAE,EAECoM,EAAmBvM,EAAAA,YAAY,IAAM,CACzCmL,EAAahL,GAASA,EAAO,EAAE,CACjC,EAAG,CAAA,CAAE,EAECqM,EAAmBxM,EAAAA,YAAY,IAAM,CACzCkL,EAAQ,CAAC,EACTC,EAAY,CAAC,CACf,EAAG,CAAA,CAAE,EAECsB,EAAqBzM,EAAAA,YAAY,IAAM,CAC3CkL,EAAQ,CAAC,CACX,EAAG,CAAA,CAAE,EAECwB,EAAmB1M,cAAaI,GAAoB,CACxD8K,EAAQ9K,CAAO,CACjB,EAAG,CAAA,CAAE,EAECuM,EAAc3M,EAAAA,YAAY,IAAM,CACpCkL,EAAQ,CAAC,EACTC,EAAY,CAAC,CACf,EAAG,CAAA,CAAE,EAECyB,EAAiB5M,EAAAA,YAAY,IAAM,CACvC,GAAI,CAAC6L,EAAa,OAClB,MAAMgB,EAAO,SAAS,cAAc,GAAG,EACvCA,EAAK,KAAOhB,EAAY,IACxBgB,EAAK,SAAWhB,EAAY,KAC5BgB,EAAK,MAAA,CACP,EAAG,CAAChB,CAAW,CAAC,EAGViB,EAAmB9M,cAAaC,GAAwB,CAC5DwL,EAAY,IAAI,EAChBF,EAActL,EAAE,cAAc,CAAC,EAAE,OAAO,CAC1C,EAAG,CAAA,CAAE,EAEC8M,EAAkB/M,cAAaC,GAAwB,CAC3DwL,EAAYxL,EAAE,cAAc,CAAC,EAAE,OAAO,CACxC,EAAG,CAAA,CAAE,EAEC+M,EAAiBhN,EAAAA,YAAY,IAAM,CACvC,GAAI,CAACsL,GAAc,CAACE,EAAU,OAC9B,MAAMlJ,EAAWgJ,EAAaE,EACxByB,EAAc3K,EAAWoJ,EACzBwB,EAAe5K,EAAW,CAACoJ,EAE7BuB,GAAepC,EAAec,EAAgB,OAAS,IACzDX,GAAA,MAAAA,EAAaH,EAAe,IAE1BqC,GAAgBrC,EAAe,IACjCG,GAAA,MAAAA,EAAaH,EAAe,GAEhC,EAAG,CAACS,EAAYE,EAAUE,EAAkBb,EAAcc,EAAgB,OAAQX,CAAU,CAAC,EAE7F,GAAI,CAACF,GAAU,CAACe,EAAa,OAAO,KAEpC,MAAMsB,EAAmBhD,IAAa,SAAWA,IAAa,MACxDiD,EAAoBjD,IAAa,QAEjCkD,EACJ5M,EAAAA,IAAC6M,EAAAA,gBAAA,CACE,SAAAxC,GACCrK,EAAAA,IAACC,EAAAA,OAAO,IAAP,CACC,QAAS,CAAE,QAAS,CAAA,EACpB,QAAS,CAAE,QAAS,CAAA,EACpB,KAAM,CAAE,QAAS,CAAA,EACjB,UAAU,uGACV,QAASqK,EACT,QAAU9K,GAAMA,EAAE,gBAAA,EAGlB,SAAAO,EAAAA,KAAC,MAAA,CACC,UAAU,uDACV,QAAUP,GAAMA,EAAE,gBAAA,EAGlB,SAAA,CAAAQ,EAAAA,IAACC,EAAAA,OAAO,IAAP,CACC,QAAS,CAAE,EAAG,IAAA,EACd,QAAS,CAAE,EAAG,CAAA,EACd,KAAM,CAAE,EAAG,IAAA,EACX,UAAU,yCAEV,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,qMAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,iEACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,qDACX,SAAAoL,EAAY,KACf,EACArL,EAAAA,KAAC,IAAA,CAAE,UAAU,mCACV,SAAA,CAAAqK,EAAe,EAAE,MAAIc,EAAgB,MAAA,CAAA,CACxC,CAAA,EACF,EAEAlL,EAAAA,IAAC,MAAA,CAAI,UAAU,iBACb,SAAAA,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAAC+M,EAAAA,EAAA,CAAE,UAAU,SAAA,CAAU,EAC7B,MAAM,KACN,QAASzC,CAAA,CAAA,CACX,CACF,CAAA,EACF,EAGAvK,EAAAA,KAAC,MAAA,CAAI,UAAU,gFACZ,SAAA,CAAA2M,GACC3M,EAAAA,KAAAiN,WAAA,CACE,SAAA,CAAAhN,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACiN,EAAAA,QAAA,CAAQ,UAAU,SAAA,CAAU,EACnC,MAAM,KACN,QAASrB,EACT,SAAU5N,GAAQ,GAAA,CAAA,EAEpB+B,EAAAA,KAAC,OAAA,CAAK,UAAU,6DACb,SAAA,CAAA,KAAK,MAAM/B,EAAO,GAAG,EAAE,GAAA,EAC1B,EACAgC,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACkN,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,EAClC,MAAM,KACN,QAASvB,EACT,SAAU3N,GAAQ,EAAA,CAAA,EAEpBgC,EAAAA,IAAC,MAAA,CAAI,UAAU,2BAAA,CAA4B,EAC3CA,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACmN,EAAAA,UAAA,CAAU,UAAU,SAAA,CAAU,EACrC,MAAM,OACN,QAASpB,CAAA,CAAA,EAEX/L,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACoN,EAAAA,UAAA,CAAU,UAAU,SAAA,CAAU,EACrC,MAAM,OACN,QAASpB,CAAA,CAAA,EAEXhM,EAAAA,IAAC,MAAA,CAAI,UAAU,2BAAA,CAA4B,CAAA,EAC7C,EAGD2M,GACC5M,EAAAA,KAAAiN,WAAA,CACE,SAAA,CAAAhN,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACqN,EAAAA,UAAA,CAAU,UAAU,SAAA,CAAU,EACrC,MAAM,OACN,QAASvB,CAAA,CAAA,EAEX9L,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACsN,EAAAA,SAAA,CAAS,UAAU,SAAA,CAAU,EACpC,MAAM,OACN,QAASzB,CAAA,CAAA,EAEX7L,EAAAA,IAAC,MAAA,CAAI,UAAU,2BAAA,CAA4B,CAAA,EAC7C,GAGA0M,GAAoBC,IACpB5M,EAAAA,KAAAiN,EAAAA,SAAA,CACE,SAAA,CAAAhN,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAACuN,EAAAA,UAAA,CAAU,UAAU,SAAA,CAAU,EACrC,MAAM,KACN,QAASrB,CAAA,CAAA,EAEXlM,EAAAA,IAAC,MAAA,CAAI,UAAU,2BAAA,CAA4B,CAAA,EAC7C,EAGFA,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAAC6J,EAAAA,SAAA,CAAS,UAAU,SAAA,CAAU,EACpC,MAAM,KACN,QAASsC,CAAA,CAAA,EAIXpM,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,UAAU,2BAAA,CAA4B,EAC3CA,EAAAA,IAAC8M,EAAA,CACC,KAAM9M,EAAAA,IAAC+M,EAAAA,EAAA,CAAE,UAAU,SAAA,CAAU,EAC7B,MAAM,KACN,QAASzC,CAAA,CAAA,CACX,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,EAIFtK,EAAAA,IAAC,MAAA,CACC,UAAU,oFACV,aAAcqM,EACd,YAAaC,EACb,WAAYC,EAEX,SAAAlB,EAECA,EAAe,OAAOD,CAAW,EAEjCrL,OAAAiN,EAAAA,SAAA,CACG,SAAA,CAAAtD,IAAa,SACZ1J,EAAAA,IAACjC,GAAA,CACC,IAAKqN,EAAY,IACjB,KAAApN,EACA,SAAAC,EACA,aAAcgO,CAAA,CAAA,EAGjBvC,IAAa,OACZ1J,EAAAA,IAACQ,GAAA,CACC,IAAK4K,EAAY,IACjB,KAAApN,EACA,YAAAyC,EACA,aAAckK,EACd,mBAAoBC,CAAA,CAAA,EAGvBlB,IAAa,QAAU1J,MAACoC,GAAA,CAAa,IAAKgJ,EAAY,IAAK,EAC3D1B,IAAa,QAAU1J,MAAC8C,GAAA,CAAa,IAAKsI,EAAY,IAAK,EAC3D1B,IAAa,QAAU1J,MAAC+D,GAAA,CAAa,IAAKqH,EAAY,IAAK,EAC3D1B,IAAa,SAAW1J,MAACyF,GAAA,CAAc,IAAK2F,EAAY,IAAK,EAC7D1B,IAAa,SACZ1J,MAACkG,GAAA,CAAc,IAAKkF,EAAY,IAAK,SAAUA,EAAY,IAAA,CAAM,EAElE1B,IAAa,YAAc1J,MAACqI,GAAA,CAAiB,IAAK+C,EAAY,IAAK,EACnE1B,IAAa,QACZ1J,MAACsJ,GAAA,CAAa,IAAK8B,EAAY,IAAK,SAAUA,EAAY,IAAA,CAAM,EAEjE1B,IAAa,eACZ1J,EAAAA,IAACyJ,GAAA,CACC,SAAU2B,EAAY,KACtB,SAAUA,EAAY,KACtB,WAAYe,CAAA,CAAA,CACd,CAAA,CAEJ,CAAA,CAAA,EAKHjB,EAAgB,OAAS,GACxBnL,EAAAA,KAAAiN,EAAAA,SAAA,CACG,SAAA,CAAA5C,EAAe,GACdpK,EAAAA,IAACC,EAAAA,OAAO,OAAP,CACC,QAAS,CAAE,EAAG,KAAM,QAAS,CAAA,EAC7B,QAAS,CAAE,EAAG,EAAG,QAAS,CAAA,EAC1B,KAAM,CAAE,EAAG,KAAM,QAAS,CAAA,EAC1B,QAAS,IAAMsK,GAAA,YAAAA,EAAaH,EAAe,GAC3C,UAAU,wOAEV,SAAApK,EAAAA,IAACwN,EAAAA,YAAA,CAAY,UAAU,uBAAA,CAAwB,CAAA,CAAA,EAIlDpD,EAAec,EAAgB,OAAS,GACvClL,EAAAA,IAACC,EAAAA,OAAO,OAAP,CACC,QAAS,CAAE,EAAG,IAAK,QAAS,CAAA,EAC5B,QAAS,CAAE,EAAG,EAAG,QAAS,CAAA,EAC1B,KAAM,CAAE,EAAG,IAAK,QAAS,CAAA,EACzB,QAAS,IAAMsK,GAAA,YAAAA,EAAaH,EAAe,GAC3C,UAAU,0OAEV,SAAApK,EAAAA,IAACyN,EAAAA,aAAA,CAAa,UAAU,uBAAA,CAAwB,CAAA,CAAA,CAClD,CAAA,CAEJ,CAAA,CAAA,CAAA,CAEJ,CAAA,EAGN,EAIF,OAAOC,gBAAad,EAAc,SAAS,IAAI,CACjD,EAUME,EAA8C,CAAC,CAAE,KAAAa,EAAM,MAAAC,EAAO,QAAAC,EAAS,SAAAC,KAEzE9N,EAAAA,IAAC,SAAA,CACC,QAAA6N,EACA,SAAAC,EACA,MAAOF,EACP,UAAW,iCAAiCE,EACxC,mCACA,iDACF,GAED,SAAAH,CAAA,CAAA,EC1cMI,GAAUC,GAAY","x_google_ignoreList":[9]}