@eternalheart/react-file-preview 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/chunks/{index-CMehLA91.mjs → index--xe_vUUO.mjs} +2 -2
- package/lib/chunks/{index-CMehLA91.mjs.map → index--xe_vUUO.mjs.map} +1 -1
- package/lib/chunks/{index-Cbp94jbP.mjs → index-B3jtj_7-.mjs} +20 -20
- package/lib/chunks/{index-Cbp94jbP.mjs.map → index-B3jtj_7-.mjs.map} +1 -1
- package/lib/chunks/{index-CmK5E5Oa.mjs → index-BJZ6GlPC.mjs} +3 -3
- package/lib/chunks/{index-CmK5E5Oa.mjs.map → index-BJZ6GlPC.mjs.map} +1 -1
- package/lib/chunks/{index-DTNdG1bB.mjs → index-B__mDGsc.mjs} +3 -3
- package/lib/chunks/{index-DTNdG1bB.mjs.map → index-B__mDGsc.mjs.map} +1 -1
- package/lib/chunks/{index-37FMdXja.mjs → index-BczRYnSp.mjs} +2 -2
- package/lib/chunks/{index-37FMdXja.mjs.map → index-BczRYnSp.mjs.map} +1 -1
- package/lib/chunks/{index-C2uu09Eb.mjs → index-Bj6cvzuN.mjs} +2 -2
- package/lib/chunks/{index-C2uu09Eb.mjs.map → index-Bj6cvzuN.mjs.map} +1 -1
- package/lib/chunks/{index-HRUhzosx.mjs → index-BjL2sXlA.mjs} +2 -2
- package/lib/chunks/{index-HRUhzosx.mjs.map → index-BjL2sXlA.mjs.map} +1 -1
- package/lib/chunks/{index-DsIUJXpz.mjs → index-BrTFkhJZ.mjs} +2 -2
- package/lib/chunks/{index-DsIUJXpz.mjs.map → index-BrTFkhJZ.mjs.map} +1 -1
- package/lib/chunks/{index-BXa7r4uK.mjs → index-BvBldLaU.mjs} +3 -3
- package/lib/chunks/{index-BXa7r4uK.mjs.map → index-BvBldLaU.mjs.map} +1 -1
- package/lib/chunks/{index-DxUP4apX.mjs → index-C6eeg9nN.mjs} +2 -2
- package/lib/chunks/{index-DxUP4apX.mjs.map → index-C6eeg9nN.mjs.map} +1 -1
- package/lib/chunks/{index-DfzgQFfx.mjs → index-CZPztWhN.mjs} +2 -2
- package/lib/chunks/{index-DfzgQFfx.mjs.map → index-CZPztWhN.mjs.map} +1 -1
- package/lib/chunks/{index-qWLZuYn6.mjs → index-Chj36kjS.mjs} +2 -2
- package/lib/chunks/{index-qWLZuYn6.mjs.map → index-Chj36kjS.mjs.map} +1 -1
- package/lib/chunks/{index-Bn0NJNzq.mjs → index-CwCdx6Io.mjs} +2 -2
- package/lib/chunks/{index-Bn0NJNzq.mjs.map → index-CwCdx6Io.mjs.map} +1 -1
- package/lib/chunks/{index-7aRho9r4.mjs → index-D3Wso9Iz.mjs} +3 -3
- package/lib/chunks/{index-7aRho9r4.mjs.map → index-D3Wso9Iz.mjs.map} +1 -1
- package/lib/chunks/{index-VnjkEX5p.mjs → index-DXZFI5Vp.mjs} +2 -2
- package/lib/chunks/{index-VnjkEX5p.mjs.map → index-DXZFI5Vp.mjs.map} +1 -1
- package/lib/chunks/{index-BaSsmMZP.mjs → index-DZC5bucC.mjs} +2 -2
- package/lib/chunks/{index-BaSsmMZP.mjs.map → index-DZC5bucC.mjs.map} +1 -1
- package/lib/chunks/{index-Btsr3v83.mjs → index-VkrsxHnU.mjs} +2 -2
- package/lib/chunks/{index-Btsr3v83.mjs.map → index-VkrsxHnU.mjs.map} +1 -1
- package/lib/chunks/{index-CTEgp9x8.mjs → index-XdWDqRwq.mjs} +2 -2
- package/lib/chunks/{index-CTEgp9x8.mjs.map → index-XdWDqRwq.mjs.map} +1 -1
- package/lib/chunks/{index-C5o_T3Es.mjs → index-wlMDzgVW.mjs} +2 -2
- package/lib/chunks/{index-C5o_T3Es.mjs.map → index-wlMDzgVW.mjs.map} +1 -1
- package/lib/chunks/{useShikiHighlight-BG7pCfB5.mjs → useShikiHighlight-DHhZ6Oy9.mjs} +2 -2
- package/lib/chunks/{useShikiHighlight-BG7pCfB5.mjs.map → useShikiHighlight-DHhZ6Oy9.mjs.map} +1 -1
- package/lib/index.cjs +45 -32
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as t, jsxs as P } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as T, useState as l, useRef as D, useEffect as b, useCallback as N, useImperativeHandle as I } from "react";
|
|
3
3
|
import R from "mammoth";
|
|
4
|
-
import { u as S, a as k } from "./index-
|
|
4
|
+
import { u as S, a as k } from "./index-B3jtj_7-.mjs";
|
|
5
5
|
import { R as $ } from "./RendererError-D5i8eSpN.mjs";
|
|
6
6
|
const H = 1123, _ = 60, v = 50, j = H - _ * 2, L = 24, E = {
|
|
7
7
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -104,4 +104,4 @@ const H = 1123, _ = 60, v = 50, j = H - _ * 2, L = 24, E = {
|
|
|
104
104
|
export {
|
|
105
105
|
O as DocxRenderer
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=index-
|
|
107
|
+
//# sourceMappingURL=index-CZPztWhN.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-CZPztWhN.mjs","sources":["../../src/renderers/Docx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport mammoth from 'mammoth';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface DocxRendererProps {\n url: string;\n}\n\n// A4 page dimensions (96dpi)\nconst PAGE_HEIGHT = 1123;\nconst PAGE_PADDING_Y = 60;\nconst PAGE_PADDING_X = 50;\nconst PAGE_CONTENT_HEIGHT = PAGE_HEIGHT - PAGE_PADDING_Y * 2;\nconst PAGE_GAP = 24;\n\nconst contentStyle: React.CSSProperties = {\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.8',\n color: '#333',\n};\n\nexport const DocxRenderer = forwardRef<RendererHandle, DocxRendererProps>(({ url }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [html, setHtml] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [pages, setPages] = useState<string[]>([]);\n const measureRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!url) return;\n\n const loadDocx = async () => {\n setLoading(true);\n setError(null);\n setHtml('');\n\n try {\n const response = await fetcher(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(t('docx.parse_failed'));\n } finally {\n setLoading(false);\n }\n };\n\n loadDocx();\n }, [url, fetcher, t]);\n\n const paginate = useCallback(() => {\n const container = measureRef.current;\n if (!container || !html) return;\n\n const children = Array.from(container.children) as HTMLElement[];\n if (children.length === 0) {\n setPages([html]);\n return;\n }\n\n const result: string[][] = [[]];\n let currentPageUsed = 0;\n\n for (const child of children) {\n const h = child.offsetHeight;\n\n // If adding this block would exceed page content area and page isn't empty,\n // start a new page\n if (currentPageUsed > 0 && currentPageUsed + h > PAGE_CONTENT_HEIGHT) {\n result.push([]);\n currentPageUsed = 0;\n }\n\n result[result.length - 1].push(child.outerHTML);\n currentPageUsed += h;\n }\n\n // At least one page\n if (result.length === 0) result.push([]);\n\n setPages(result.map(blocks => blocks.join('')));\n }, [html]);\n\n useEffect(() => {\n if (!html || !measureRef.current) return;\n requestAnimationFrame(() => {\n paginate();\n });\n }, [html, paginate]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return <RendererError message={error} />;\n }\n\n return (\n <div\n className=\"rfp-docx-container rfp-w-full rfp-h-full rfp-overflow-auto rfp-py-6 rfp-px-4\"\n style={{ background: 'rgba(0, 0, 0, 0.15)' }}\n >\n {/* Hidden measurement div — same width as page content area */}\n <div\n ref={measureRef}\n dangerouslySetInnerHTML={{ __html: html }}\n style={{\n ...contentStyle,\n position: 'absolute',\n visibility: 'hidden',\n width: `${794 - PAGE_PADDING_X * 2}px`,\n pointerEvents: 'none',\n }}\n />\n\n {/* Visible pages */}\n <div\n className=\"rfp-flex rfp-flex-col rfp-items-center\"\n style={{ gap: `${PAGE_GAP}px` }}\n >\n {(pages.length > 0 ? pages : ['']).map((pageHtml, i) => (\n <div\n key={i}\n style={{\n width: '100%',\n maxWidth: '794px',\n minHeight: `${PAGE_HEIGHT}px`,\n background: 'white',\n boxShadow: '0 4px 6px rgba(0, 0, 0, 0.07), 0 10px 20px rgba(0, 0, 0, 0.10)',\n flexShrink: 0,\n padding: `${PAGE_PADDING_Y}px ${PAGE_PADDING_X}px`,\n }}\n >\n <div\n dangerouslySetInnerHTML={{ __html: pageHtml }}\n style={contentStyle}\n />\n </div>\n ))}\n </div>\n </div>\n );\n});\n"],"names":["PAGE_HEIGHT","PAGE_PADDING_Y","PAGE_PADDING_X","PAGE_CONTENT_HEIGHT","PAGE_GAP","contentStyle","DocxRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","html","setHtml","useState","loading","setLoading","error","setError","pages","setPages","measureRef","useRef","useEffect","response","arrayBuffer","result","mammoth","err","paginate","useCallback","container","children","currentPageUsed","child","h","blocks","useImperativeHandle","jsx","RendererError","jsxs","pageHtml","i"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as o, jsxs as R } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as ce, useState as P, useRef as k, useCallback as l, useEffect as m, useImperativeHandle as ie } from "react";
|
|
3
|
-
import { u as le } from "./index-
|
|
3
|
+
import { u as le } from "./index-B3jtj_7-.mjs";
|
|
4
4
|
import { R as fe } from "./RendererError-D5i8eSpN.mjs";
|
|
5
5
|
import { Menu as ue, ChevronLeft as pe, ChevronRight as de, ZoomOut as me, ZoomIn as ge, RefreshCw as he, X as be } from "lucide-react";
|
|
6
6
|
import * as ye from "pdfjs-dist/build/pdf.mjs";
|
|
@@ -310,4 +310,4 @@ const ke = ce(({
|
|
|
310
310
|
export {
|
|
311
311
|
ke as PdfRenderer
|
|
312
312
|
};
|
|
313
|
-
//# sourceMappingURL=index-
|
|
313
|
+
//# sourceMappingURL=index-Chj36kjS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-qWLZuYn6.mjs","sources":["../../src/renderers/Pdf/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { RendererError } from '../RendererError';\nimport { X, ZoomIn, ZoomOut, ChevronLeft, ChevronRight, Menu, RefreshCw } from 'lucide-react';\nimport type { RendererHandle } from '../base.types';\nimport type { ToolbarGroup } from '../toolbar.types';\n// @ts-ignore - pdfjs-dist 类型路径\nimport * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';\n\ninterface PdfOutlineItem {\n title: string;\n dest: any;\n items?: PdfOutlineItem[];\n}\n\ninterface PdfPageProxy {\n getViewport(opts: { scale: number }): { width: number; height: number };\n render(opts: { canvasContext: CanvasRenderingContext2D; viewport: { width: number; height: number } }): {\n promise: Promise<void>;\n cancel(): void;\n };\n}\n\ninterface PdfDocumentProxy {\n numPages: number;\n getPage(pageNumber: number): Promise<PdfPageProxy>;\n getOutline(): Promise<PdfOutlineItem[] | null>;\n destroy(): void;\n}\n\ninterface PageState {\n element: HTMLDivElement;\n rendered: boolean;\n rendering: boolean;\n renderTask: { cancel(): void } | null;\n}\n\nexport interface PdfRendererHandle extends RendererHandle {\n // 可选的公开方法\n}\n\ninterface PdfRendererProps {\n url: string;\n}\n\nexport const PdfRenderer = forwardRef<PdfRendererHandle, PdfRendererProps>(({\n url,\n}, ref) => {\n const t = useTranslator();\n\n // 内部状态管理\n const [zoom, setZoom] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [numPages, setNumPages] = useState<number>(0);\n const [showOutline, setShowOutline] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [outline, setOutline] = useState<PdfOutlineItem[]>([]);\n const [activeOutlineItem, setActiveOutlineItem] = useState<string | null>(null);\n const outlinePageMapRef = useRef<Map<string, number>>(new Map());\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const pdfDocRef = useRef<PdfDocumentProxy | null>(null);\n const pageStatesRef = useRef<Map<number, PageState>>(new Map());\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n // 事件发射器:用于通知主组件工具栏状态变化\n const listenersRef = useRef<Set<() => void>>(new Set());\n const notifyToolbarChange = useCallback(() => {\n listenersRef.current.forEach(listener => listener());\n }, []);\n\n // 监听影响工具栏的状态变化\n useEffect(() => {\n notifyToolbarChange();\n }, [zoom, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [currentPage, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [numPages, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [outline.length, notifyToolbarChange]);\n\n // 渲染单个页面\n const renderPage = useCallback(async (pageNumber: number, scale: number) => {\n if (!pdfDocRef.current) return;\n const state = pageStatesRef.current.get(pageNumber);\n if (!state || state.rendering) return;\n\n state.rendering = true;\n\n try {\n const page = await pdfDocRef.current.getPage(pageNumber);\n const viewport = page.getViewport({ scale });\n\n const canvas = document.createElement('canvas');\n canvas.width = viewport.width;\n canvas.height = viewport.height;\n canvas.style.maxWidth = '100%';\n canvas.style.height = 'auto';\n canvas.style.borderRadius = '0';\n canvas.style.display = 'block';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const renderTask = page.render({ canvasContext: ctx, viewport });\n state.renderTask = renderTask;\n await renderTask.promise;\n\n state.element.innerHTML = '';\n state.element.appendChild(canvas);\n\n state.rendered = true;\n } catch (err: any) {\n if (err?.name !== 'RenderingCancelledException') {\n console.error(`渲染页面 ${pageNumber} 失败:`, err);\n }\n } finally {\n state.rendering = false;\n state.renderTask = null;\n }\n }, []);\n\n // 清理页面 canvas\n const clearPageCanvas = useCallback((pageNumber: number) => {\n const state = pageStatesRef.current.get(pageNumber);\n if (!state) return;\n\n // 取消正在进行的渲染\n if (state.renderTask) {\n state.renderTask.cancel();\n state.renderTask = null;\n }\n\n // 清理 canvas\n const canvas = state.element.querySelector('canvas');\n if (canvas) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n canvas.remove();\n }\n\n state.element.innerHTML = '';\n state.rendered = false;\n state.rendering = false;\n }, []);\n\n // 初始化页面占位符\n // 构建大纲-页码映射\n const buildOutlinePageMap = async (items: PdfOutlineItem[], pdfDoc: PdfDocumentProxy, depth = 0) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const itemKey = `${item.title}-${i}-${depth}`;\n\n try {\n let pageNumber: number | null = null;\n const dest = item.dest;\n\n if (typeof dest === 'string') {\n const namedDest = await (pdfDoc as any).getDestination?.(dest);\n if (namedDest && namedDest[0] && typeof namedDest[0] === 'object') {\n pageNumber = await (pdfDoc as any).getPageIndex?.(namedDest[0]) + 1;\n }\n } else if (Array.isArray(dest) && dest[0] && typeof dest[0] === 'object') {\n pageNumber = await (pdfDoc as any).getPageIndex?.(dest[0]) + 1;\n }\n\n if (pageNumber !== null && pageNumber > 0) {\n outlinePageMapRef.current.set(itemKey, pageNumber);\n }\n\n if (item.items && item.items.length > 0) {\n await buildOutlinePageMap(item.items, pdfDoc, depth + 1);\n }\n } catch (err) {\n // 静默失败,某些大纲项可能无法映射到页码\n }\n }\n };\n\n // 根据当前页码更新激活的大纲项\n const updateActiveOutlineByPage = useCallback((page: number) => {\n let closestItem: string | null = null;\n let closestDistance = Infinity;\n\n outlinePageMapRef.current.forEach((itemPage, itemKey) => {\n if (itemPage <= page) {\n const distance = page - itemPage;\n if (distance < closestDistance) {\n closestDistance = distance;\n closestItem = itemKey;\n }\n }\n });\n\n if (closestItem !== activeOutlineItem) {\n setActiveOutlineItem(closestItem);\n }\n }, [activeOutlineItem]);\n\n // 监听页码变化,更新大纲高亮\n useEffect(() => {\n if (currentPage > 0 && outlinePageMapRef.current.size > 0) {\n updateActiveOutlineByPage(currentPage);\n }\n }, [currentPage, updateActiveOutlineByPage]);\n\n const initPagePlaceholders = useCallback(() => {\n if (!pdfDocRef.current || !scrollContainerRef.current) return;\n\n const wrapper = scrollContainerRef.current.querySelector('.pdf-pages') as HTMLDivElement | null;\n if (!wrapper) return;\n\n wrapper.innerHTML = '';\n pageStatesRef.current.clear();\n\n for (let i = 1; i <= numPages; i++) {\n const pageDiv = document.createElement('div');\n pageDiv.className = 'rfp-pdf-page-placeholder rfp-relative rfp-flex rfp-justify-center';\n pageDiv.setAttribute('data-page-number', String(i));\n wrapper.appendChild(pageDiv);\n\n pageStatesRef.current.set(i, {\n element: pageDiv,\n rendered: false,\n rendering: false,\n renderTask: null,\n });\n\n // 观察页面元素\n if (observerRef.current) {\n observerRef.current.observe(pageDiv);\n }\n }\n }, [numPages]);\n\n // 加载 PDF 文档\n const loadPdf = useCallback(async () => {\n setError(null);\n setIsLoading(true);\n setNumPages(0);\n\n if (pdfDocRef.current) {\n try {\n pdfDocRef.current.destroy();\n } catch {\n // ignore\n }\n pdfDocRef.current = null;\n }\n\n try {\n const loadingTask = pdfjsLib.getDocument({ url });\n pdfDocRef.current = (await loadingTask.promise) as PdfDocumentProxy;\n const total = pdfDocRef.current.numPages;\n\n setNumPages(total);\n setCurrentPage(1);\n\n // 提取大纲\n try {\n const outlineData = await pdfDocRef.current.getOutline();\n if (outlineData) {\n setOutline(outlineData);\n // 构建大纲-页码映射\n outlinePageMapRef.current.clear();\n await buildOutlinePageMap(outlineData, pdfDocRef.current);\n }\n } catch (err) {\n console.warn('PDF 大纲提取失败:', err);\n }\n\n setIsLoading(false);\n } catch (err) {\n console.error('PDF 加载错误:', err);\n setError(t('pdf.load_failed'));\n setIsLoading(false);\n }\n }, [url, t]);\n\n // 滚动处理\n const handleScroll = useCallback(() => {\n if (!scrollContainerRef.current || pageStatesRef.current.size === 0) return;\n\n const container = scrollContainerRef.current;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageStatesRef.current.forEach((state, pageNumber) => {\n const rect = state.element.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 setCurrentPage(currentVisiblePage);\n }\n }, [currentPage]);\n\n // 初始化 IntersectionObserver\n useEffect(() => {\n observerRef.current = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const pageNumber = Number(entry.target.getAttribute('data-page-number'));\n if (!pageNumber) return;\n\n if (entry.isIntersecting) {\n // 页面进入视口,渲染\n renderPage(pageNumber, zoom);\n } else {\n // 页面离开视口,清理\n const state = pageStatesRef.current.get(pageNumber);\n if (state && state.rendered) {\n clearPageCanvas(pageNumber);\n }\n }\n });\n },\n {\n root: scrollContainerRef.current,\n rootMargin: '500px 0px',\n threshold: 0,\n }\n );\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n };\n }, [zoom, renderPage, clearPageCanvas]);\n\n // 监听 URL 变化\n useEffect(() => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (url) {\n loadPdf();\n }\n }, [url, loadPdf]);\n\n // 监听 numPages 变化,初始化占位符\n useEffect(() => {\n if (numPages > 0) {\n // 等待 DOM 更新后初始化占位符\n setTimeout(() => {\n initPagePlaceholders();\n }, 0);\n }\n }, [numPages, initPagePlaceholders]);\n\n // 监听 zoom 变化(防抖)\n useEffect(() => {\n const timer = setTimeout(() => {\n // 清理所有已渲染页面\n pageStatesRef.current.forEach((state, pageNumber) => {\n if (state.rendered) {\n clearPageCanvas(pageNumber);\n }\n });\n\n // 触发重新渲染\n if (observerRef.current && scrollContainerRef.current) {\n pageStatesRef.current.forEach((state) => {\n observerRef.current?.unobserve(state.element);\n observerRef.current?.observe(state.element);\n });\n }\n }, 150);\n\n return () => clearTimeout(timer);\n }, [zoom, clearPageCanvas]);\n\n // 监听滚动事件\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [handleScroll]);\n\n // 清理\n useEffect(() => {\n return () => {\n // 清理所有渲染任务\n pageStatesRef.current.forEach((state) => {\n if (state.renderTask) {\n state.renderTask.cancel();\n }\n });\n pageStatesRef.current.clear();\n\n if (pdfDocRef.current) {\n try {\n pdfDocRef.current.destroy();\n } catch {\n // ignore\n }\n pdfDocRef.current = null;\n }\n };\n }, []);\n\n // 处理大纲点击跳转\n const handleOutlineClick = useCallback(async (dest: any, itemKey: string, onClose?: () => void) => {\n if (!pdfDocRef.current || !scrollContainerRef.current) return;\n\n try {\n let pageNumber: number;\n\n if (typeof dest === 'string') {\n // 命名目标\n const namedDest = await (pdfDocRef.current as any).getDestination(dest);\n if (namedDest && namedDest[0]) {\n const pageRef = namedDest[0];\n pageNumber = await (pdfDocRef.current as any).getPageIndex(pageRef) + 1;\n } else {\n return;\n }\n } else if (Array.isArray(dest) && dest[0]) {\n // 直接页面引用\n const pageRef = dest[0];\n pageNumber = await (pdfDocRef.current as any).getPageIndex(pageRef) + 1;\n } else {\n return;\n }\n\n // 设置激活项\n setActiveOutlineItem(itemKey);\n\n // 滚动到目标页面\n const pages = scrollContainerRef.current.querySelectorAll('[data-page-number]');\n const targetPage = pages[pageNumber - 1];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n\n // 跳转后自动关闭侧边栏\n if (onClose) {\n setTimeout(() => onClose(), 300);\n }\n } catch (err) {\n console.error('大纲跳转失败:', err);\n }\n }, []);\n\n // 渲染大纲项\n const renderOutlineItems = (items: PdfOutlineItem[], depth = 0, onClose?: () => void): React.ReactNode => {\n return (\n <ul style={{ marginLeft: depth > 0 ? 16 : 0 }}>\n {items.map((item, i) => {\n const itemKey = `${item.title}-${i}-${depth}`;\n const isActive = activeOutlineItem === itemKey;\n return (\n <li key={itemKey}>\n <button\n onClick={() => handleOutlineClick(item.dest, itemKey, onClose)}\n className={`rfp-w-full rfp-text-left rfp-py-2 rfp-px-3 rfp-text-sm rfp-rounded rfp-transition-all rfp-truncate ${\n isActive\n ? 'rfp-bg-surface-2 rfp-text-fg-primary rfp-font-medium'\n : 'rfp-text-fg-secondary hover:rfp-text-fg-primary hover:rfp-bg-surface-2'\n }`}\n title={item.title}\n >\n {item.title}\n </button>\n {item.items && item.items.length > 0 && renderOutlineItems(item.items, depth + 1, onClose)}\n </li>\n );\n })}\n </ul>\n );\n };\n\n // 工具栏事件处理\n const handleZoomIn = useCallback(() => {\n setZoom(z => Math.min(z + 0.1, 3));\n }, []);\n\n const handleZoomOut = useCallback(() => {\n setZoom(z => Math.max(z - 0.1, 0.5));\n }, []);\n\n const handleReset = useCallback(() => {\n setZoom(1);\n }, []);\n\n const handlePrevPage = useCallback(() => {\n if (!scrollContainerRef.current) return;\n const container = scrollContainerRef.current;\n const pages = container.querySelectorAll('[data-page-number]');\n const targetPage = pages[Math.max(0, currentPage - 2)];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n }, [currentPage]);\n\n const handleNextPage = useCallback(() => {\n if (!scrollContainerRef.current) return;\n const container = scrollContainerRef.current;\n const pages = container.querySelectorAll('[data-page-number]');\n const targetPage = pages[Math.min(pages.length - 1, currentPage)];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n }, [currentPage, numPages]);\n\n const handleToggleOutline = useCallback(() => {\n setShowOutline(prev => !prev);\n }, []);\n\n // 工具栏配置\n const getToolbarGroups = useCallback((): ToolbarGroup[] => {\n const groups: ToolbarGroup[] = [];\n\n // 大纲按钮(如果有大纲)\n if (outline.length > 0) {\n groups.push({\n items: [\n { type: 'button', icon: <Menu className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.outline'), action: handleToggleOutline, active: showOutline },\n ],\n });\n }\n\n // 翻页\n groups.push({\n items: [\n { type: 'button', icon: <ChevronLeft className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.prev_page'), action: handlePrevPage, disabled: currentPage <= 1 },\n { type: 'text', content: `${currentPage} / ${numPages}`, minWidth: '4rem' },\n { type: 'button', icon: <ChevronRight className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.next_page'), action: handleNextPage, disabled: currentPage >= numPages },\n ],\n });\n\n // 缩放\n groups.push({\n items: [\n { type: 'button', icon: <ZoomOut className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.zoom_out'), action: handleZoomOut, disabled: zoom <= 0.5 },\n { type: 'text', content: `${Math.round(zoom * 100)}%`, minWidth: '3rem' },\n { type: 'button', icon: <ZoomIn className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.zoom_in'), action: handleZoomIn, disabled: zoom >= 3 },\n ],\n });\n\n // 重置\n groups.push({\n items: [\n { type: 'button', icon: <RefreshCw className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.reset'), action: handleReset },\n ],\n });\n\n return groups;\n }, [zoom, currentPage, numPages, showOutline, outline.length, t, handleZoomIn, handleZoomOut, handlePrevPage, handleNextPage, handleToggleOutline, handleReset]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups,\n onToolbarChange: (listener: () => void) => {\n listenersRef.current.add(listener);\n return () => listenersRef.current.delete(listener);\n },\n }), [getToolbarGroups]);\n\n return (\n <div ref={containerRef} className=\"rfp-relative rfp-w-full rfp-h-full\">\n {/* 大纲侧边栏 */}\n {outline.length > 0 && (\n <div\n className=\"rfp-absolute rfp-inset-0 rfp-z-20 rfp-flex rfp-transition-opacity rfp-duration-300\"\n style={{\n opacity: showOutline ? 1 : 0,\n pointerEvents: showOutline ? 'auto' : 'none',\n }}\n >\n <div\n className=\"rfp-w-72 rfp-max-w-[80%] rfp-h-full rfp-bg-surface-overlay rfp-backdrop-blur-xl rfp-border-r rfp-border-line-weak rfp-flex rfp-flex-col rfp-shadow-2xl rfp-transition-transform rfp-duration-300\"\n style={{ transform: showOutline ? 'translateX(0)' : 'translateX(-100%)' }}\n >\n <div className=\"rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-3 rfp-border-b rfp-border-line-weak rfp-flex-shrink-0\">\n <span className=\"rfp-text-fg-primary rfp-font-medium rfp-text-sm\">{t('toolbar.outline')}</span>\n <button\n onClick={() => setShowOutline(false)}\n className=\"rfp-text-fg-tertiary hover:rfp-text-fg-primary rfp-transition-colors\"\n >\n <X className=\"rfp-w-4 rfp-h-4\" />\n </button>\n </div>\n <div className=\"rfp-flex-1 rfp-overflow-y-auto rfp-py-4 rfp-px-1\">\n {renderOutlineItems(outline, 0, () => setShowOutline(false))}\n </div>\n </div>\n <div\n className=\"rfp-flex-1 rfp-transition-opacity rfp-duration-300\"\n style={{ background: showOutline ? 'rgba(0,0,0,0.3)' : 'transparent' }}\n onClick={() => setShowOutline(false)}\n />\n </div>\n )}\n\n <div\n ref={scrollContainerRef}\n className=\"rfp-pdf-container rfp-w-full rfp-h-full rfp-overflow-auto rfp-py-6 rfp-px-4\"\n >\n {error && (\n <RendererError message={error} />\n )}\n\n {!error && isLoading && (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-min-h-screen\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n )}\n\n {!error && (\n <div className=\"rfp-flex rfp-flex-col rfp-items-center\">\n <div className=\"pdf-pages rfp-flex rfp-flex-col rfp-gap-4\" />\n </div>\n )}\n </div>\n </div>\n );\n});\n"],"names":["PdfRenderer","forwardRef","url","ref","t","useTranslator","zoom","setZoom","useState","currentPage","setCurrentPage","numPages","setNumPages","showOutline","setShowOutline","error","setError","isLoading","setIsLoading","outline","setOutline","activeOutlineItem","setActiveOutlineItem","outlinePageMapRef","useRef","containerRef","scrollContainerRef","pdfDocRef","pageStatesRef","observerRef","listenersRef","notifyToolbarChange","useCallback","listener","useEffect","renderPage","pageNumber","scale","state","page","viewport","canvas","ctx","renderTask","err","clearPageCanvas","buildOutlinePageMap","items","pdfDoc","depth","i","item","itemKey","dest","namedDest","_a","_b","_c","updateActiveOutlineByPage","closestItem","closestDistance","itemPage","distance","initPagePlaceholders","wrapper","pageDiv","loadPdf","loadingTask","pdfjsLib","total","outlineData","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","rect","containerRect","pageCenter","entries","entry","timer","handleOutlineClick","onClose","pageRef","targetPage","renderOutlineItems","jsx","handleZoomIn","z","handleZoomOut","handleReset","handlePrevPage","handleNextPage","pages","handleToggleOutline","prev","getToolbarGroups","groups","Menu","ChevronLeft","ChevronRight","ZoomOut","ZoomIn","RefreshCw","useImperativeHandle","jsxs","X","RendererError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-Chj36kjS.mjs","sources":["../../src/renderers/Pdf/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { RendererError } from '../RendererError';\nimport { X, ZoomIn, ZoomOut, ChevronLeft, ChevronRight, Menu, RefreshCw } from 'lucide-react';\nimport type { RendererHandle } from '../base.types';\nimport type { ToolbarGroup } from '../toolbar.types';\n// @ts-ignore - pdfjs-dist 类型路径\nimport * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';\n\ninterface PdfOutlineItem {\n title: string;\n dest: any;\n items?: PdfOutlineItem[];\n}\n\ninterface PdfPageProxy {\n getViewport(opts: { scale: number }): { width: number; height: number };\n render(opts: { canvasContext: CanvasRenderingContext2D; viewport: { width: number; height: number } }): {\n promise: Promise<void>;\n cancel(): void;\n };\n}\n\ninterface PdfDocumentProxy {\n numPages: number;\n getPage(pageNumber: number): Promise<PdfPageProxy>;\n getOutline(): Promise<PdfOutlineItem[] | null>;\n destroy(): void;\n}\n\ninterface PageState {\n element: HTMLDivElement;\n rendered: boolean;\n rendering: boolean;\n renderTask: { cancel(): void } | null;\n}\n\nexport interface PdfRendererHandle extends RendererHandle {\n // 可选的公开方法\n}\n\ninterface PdfRendererProps {\n url: string;\n}\n\nexport const PdfRenderer = forwardRef<PdfRendererHandle, PdfRendererProps>(({\n url,\n}, ref) => {\n const t = useTranslator();\n\n // 内部状态管理\n const [zoom, setZoom] = useState(1);\n const [currentPage, setCurrentPage] = useState(1);\n const [numPages, setNumPages] = useState<number>(0);\n const [showOutline, setShowOutline] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [outline, setOutline] = useState<PdfOutlineItem[]>([]);\n const [activeOutlineItem, setActiveOutlineItem] = useState<string | null>(null);\n const outlinePageMapRef = useRef<Map<string, number>>(new Map());\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const pdfDocRef = useRef<PdfDocumentProxy | null>(null);\n const pageStatesRef = useRef<Map<number, PageState>>(new Map());\n const observerRef = useRef<IntersectionObserver | null>(null);\n\n // 事件发射器:用于通知主组件工具栏状态变化\n const listenersRef = useRef<Set<() => void>>(new Set());\n const notifyToolbarChange = useCallback(() => {\n listenersRef.current.forEach(listener => listener());\n }, []);\n\n // 监听影响工具栏的状态变化\n useEffect(() => {\n notifyToolbarChange();\n }, [zoom, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [currentPage, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [numPages, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [outline.length, notifyToolbarChange]);\n\n // 渲染单个页面\n const renderPage = useCallback(async (pageNumber: number, scale: number) => {\n if (!pdfDocRef.current) return;\n const state = pageStatesRef.current.get(pageNumber);\n if (!state || state.rendering) return;\n\n state.rendering = true;\n\n try {\n const page = await pdfDocRef.current.getPage(pageNumber);\n const viewport = page.getViewport({ scale });\n\n const canvas = document.createElement('canvas');\n canvas.width = viewport.width;\n canvas.height = viewport.height;\n canvas.style.maxWidth = '100%';\n canvas.style.height = 'auto';\n canvas.style.borderRadius = '0';\n canvas.style.display = 'block';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const renderTask = page.render({ canvasContext: ctx, viewport });\n state.renderTask = renderTask;\n await renderTask.promise;\n\n state.element.innerHTML = '';\n state.element.appendChild(canvas);\n\n state.rendered = true;\n } catch (err: any) {\n if (err?.name !== 'RenderingCancelledException') {\n console.error(`渲染页面 ${pageNumber} 失败:`, err);\n }\n } finally {\n state.rendering = false;\n state.renderTask = null;\n }\n }, []);\n\n // 清理页面 canvas\n const clearPageCanvas = useCallback((pageNumber: number) => {\n const state = pageStatesRef.current.get(pageNumber);\n if (!state) return;\n\n // 取消正在进行的渲染\n if (state.renderTask) {\n state.renderTask.cancel();\n state.renderTask = null;\n }\n\n // 清理 canvas\n const canvas = state.element.querySelector('canvas');\n if (canvas) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n canvas.remove();\n }\n\n state.element.innerHTML = '';\n state.rendered = false;\n state.rendering = false;\n }, []);\n\n // 初始化页面占位符\n // 构建大纲-页码映射\n const buildOutlinePageMap = async (items: PdfOutlineItem[], pdfDoc: PdfDocumentProxy, depth = 0) => {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const itemKey = `${item.title}-${i}-${depth}`;\n\n try {\n let pageNumber: number | null = null;\n const dest = item.dest;\n\n if (typeof dest === 'string') {\n const namedDest = await (pdfDoc as any).getDestination?.(dest);\n if (namedDest && namedDest[0] && typeof namedDest[0] === 'object') {\n pageNumber = await (pdfDoc as any).getPageIndex?.(namedDest[0]) + 1;\n }\n } else if (Array.isArray(dest) && dest[0] && typeof dest[0] === 'object') {\n pageNumber = await (pdfDoc as any).getPageIndex?.(dest[0]) + 1;\n }\n\n if (pageNumber !== null && pageNumber > 0) {\n outlinePageMapRef.current.set(itemKey, pageNumber);\n }\n\n if (item.items && item.items.length > 0) {\n await buildOutlinePageMap(item.items, pdfDoc, depth + 1);\n }\n } catch (err) {\n // 静默失败,某些大纲项可能无法映射到页码\n }\n }\n };\n\n // 根据当前页码更新激活的大纲项\n const updateActiveOutlineByPage = useCallback((page: number) => {\n let closestItem: string | null = null;\n let closestDistance = Infinity;\n\n outlinePageMapRef.current.forEach((itemPage, itemKey) => {\n if (itemPage <= page) {\n const distance = page - itemPage;\n if (distance < closestDistance) {\n closestDistance = distance;\n closestItem = itemKey;\n }\n }\n });\n\n if (closestItem !== activeOutlineItem) {\n setActiveOutlineItem(closestItem);\n }\n }, [activeOutlineItem]);\n\n // 监听页码变化,更新大纲高亮\n useEffect(() => {\n if (currentPage > 0 && outlinePageMapRef.current.size > 0) {\n updateActiveOutlineByPage(currentPage);\n }\n }, [currentPage, updateActiveOutlineByPage]);\n\n const initPagePlaceholders = useCallback(() => {\n if (!pdfDocRef.current || !scrollContainerRef.current) return;\n\n const wrapper = scrollContainerRef.current.querySelector('.pdf-pages') as HTMLDivElement | null;\n if (!wrapper) return;\n\n wrapper.innerHTML = '';\n pageStatesRef.current.clear();\n\n for (let i = 1; i <= numPages; i++) {\n const pageDiv = document.createElement('div');\n pageDiv.className = 'rfp-pdf-page-placeholder rfp-relative rfp-flex rfp-justify-center';\n pageDiv.setAttribute('data-page-number', String(i));\n wrapper.appendChild(pageDiv);\n\n pageStatesRef.current.set(i, {\n element: pageDiv,\n rendered: false,\n rendering: false,\n renderTask: null,\n });\n\n // 观察页面元素\n if (observerRef.current) {\n observerRef.current.observe(pageDiv);\n }\n }\n }, [numPages]);\n\n // 加载 PDF 文档\n const loadPdf = useCallback(async () => {\n setError(null);\n setIsLoading(true);\n setNumPages(0);\n\n if (pdfDocRef.current) {\n try {\n pdfDocRef.current.destroy();\n } catch {\n // ignore\n }\n pdfDocRef.current = null;\n }\n\n try {\n const loadingTask = pdfjsLib.getDocument({ url });\n pdfDocRef.current = (await loadingTask.promise) as PdfDocumentProxy;\n const total = pdfDocRef.current.numPages;\n\n setNumPages(total);\n setCurrentPage(1);\n\n // 提取大纲\n try {\n const outlineData = await pdfDocRef.current.getOutline();\n if (outlineData) {\n setOutline(outlineData);\n // 构建大纲-页码映射\n outlinePageMapRef.current.clear();\n await buildOutlinePageMap(outlineData, pdfDocRef.current);\n }\n } catch (err) {\n console.warn('PDF 大纲提取失败:', err);\n }\n\n setIsLoading(false);\n } catch (err) {\n console.error('PDF 加载错误:', err);\n setError(t('pdf.load_failed'));\n setIsLoading(false);\n }\n }, [url, t]);\n\n // 滚动处理\n const handleScroll = useCallback(() => {\n if (!scrollContainerRef.current || pageStatesRef.current.size === 0) return;\n\n const container = scrollContainerRef.current;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageStatesRef.current.forEach((state, pageNumber) => {\n const rect = state.element.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 setCurrentPage(currentVisiblePage);\n }\n }, [currentPage]);\n\n // 初始化 IntersectionObserver\n useEffect(() => {\n observerRef.current = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const pageNumber = Number(entry.target.getAttribute('data-page-number'));\n if (!pageNumber) return;\n\n if (entry.isIntersecting) {\n // 页面进入视口,渲染\n renderPage(pageNumber, zoom);\n } else {\n // 页面离开视口,清理\n const state = pageStatesRef.current.get(pageNumber);\n if (state && state.rendered) {\n clearPageCanvas(pageNumber);\n }\n }\n });\n },\n {\n root: scrollContainerRef.current,\n rootMargin: '500px 0px',\n threshold: 0,\n }\n );\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n };\n }, [zoom, renderPage, clearPageCanvas]);\n\n // 监听 URL 变化\n useEffect(() => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (url) {\n loadPdf();\n }\n }, [url, loadPdf]);\n\n // 监听 numPages 变化,初始化占位符\n useEffect(() => {\n if (numPages > 0) {\n // 等待 DOM 更新后初始化占位符\n setTimeout(() => {\n initPagePlaceholders();\n }, 0);\n }\n }, [numPages, initPagePlaceholders]);\n\n // 监听 zoom 变化(防抖)\n useEffect(() => {\n const timer = setTimeout(() => {\n // 清理所有已渲染页面\n pageStatesRef.current.forEach((state, pageNumber) => {\n if (state.rendered) {\n clearPageCanvas(pageNumber);\n }\n });\n\n // 触发重新渲染\n if (observerRef.current && scrollContainerRef.current) {\n pageStatesRef.current.forEach((state) => {\n observerRef.current?.unobserve(state.element);\n observerRef.current?.observe(state.element);\n });\n }\n }, 150);\n\n return () => clearTimeout(timer);\n }, [zoom, clearPageCanvas]);\n\n // 监听滚动事件\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [handleScroll]);\n\n // 清理\n useEffect(() => {\n return () => {\n // 清理所有渲染任务\n pageStatesRef.current.forEach((state) => {\n if (state.renderTask) {\n state.renderTask.cancel();\n }\n });\n pageStatesRef.current.clear();\n\n if (pdfDocRef.current) {\n try {\n pdfDocRef.current.destroy();\n } catch {\n // ignore\n }\n pdfDocRef.current = null;\n }\n };\n }, []);\n\n // 处理大纲点击跳转\n const handleOutlineClick = useCallback(async (dest: any, itemKey: string, onClose?: () => void) => {\n if (!pdfDocRef.current || !scrollContainerRef.current) return;\n\n try {\n let pageNumber: number;\n\n if (typeof dest === 'string') {\n // 命名目标\n const namedDest = await (pdfDocRef.current as any).getDestination(dest);\n if (namedDest && namedDest[0]) {\n const pageRef = namedDest[0];\n pageNumber = await (pdfDocRef.current as any).getPageIndex(pageRef) + 1;\n } else {\n return;\n }\n } else if (Array.isArray(dest) && dest[0]) {\n // 直接页面引用\n const pageRef = dest[0];\n pageNumber = await (pdfDocRef.current as any).getPageIndex(pageRef) + 1;\n } else {\n return;\n }\n\n // 设置激活项\n setActiveOutlineItem(itemKey);\n\n // 滚动到目标页面\n const pages = scrollContainerRef.current.querySelectorAll('[data-page-number]');\n const targetPage = pages[pageNumber - 1];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n\n // 跳转后自动关闭侧边栏\n if (onClose) {\n setTimeout(() => onClose(), 300);\n }\n } catch (err) {\n console.error('大纲跳转失败:', err);\n }\n }, []);\n\n // 渲染大纲项\n const renderOutlineItems = (items: PdfOutlineItem[], depth = 0, onClose?: () => void): React.ReactNode => {\n return (\n <ul style={{ marginLeft: depth > 0 ? 16 : 0 }}>\n {items.map((item, i) => {\n const itemKey = `${item.title}-${i}-${depth}`;\n const isActive = activeOutlineItem === itemKey;\n return (\n <li key={itemKey}>\n <button\n onClick={() => handleOutlineClick(item.dest, itemKey, onClose)}\n className={`rfp-w-full rfp-text-left rfp-py-2 rfp-px-3 rfp-text-sm rfp-rounded rfp-transition-all rfp-truncate ${\n isActive\n ? 'rfp-bg-surface-2 rfp-text-fg-primary rfp-font-medium'\n : 'rfp-text-fg-secondary hover:rfp-text-fg-primary hover:rfp-bg-surface-2'\n }`}\n title={item.title}\n >\n {item.title}\n </button>\n {item.items && item.items.length > 0 && renderOutlineItems(item.items, depth + 1, onClose)}\n </li>\n );\n })}\n </ul>\n );\n };\n\n // 工具栏事件处理\n const handleZoomIn = useCallback(() => {\n setZoom(z => Math.min(z + 0.1, 3));\n }, []);\n\n const handleZoomOut = useCallback(() => {\n setZoom(z => Math.max(z - 0.1, 0.5));\n }, []);\n\n const handleReset = useCallback(() => {\n setZoom(1);\n }, []);\n\n const handlePrevPage = useCallback(() => {\n if (!scrollContainerRef.current) return;\n const container = scrollContainerRef.current;\n const pages = container.querySelectorAll('[data-page-number]');\n const targetPage = pages[Math.max(0, currentPage - 2)];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n }, [currentPage]);\n\n const handleNextPage = useCallback(() => {\n if (!scrollContainerRef.current) return;\n const container = scrollContainerRef.current;\n const pages = container.querySelectorAll('[data-page-number]');\n const targetPage = pages[Math.min(pages.length - 1, currentPage)];\n if (targetPage) {\n targetPage.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n }, [currentPage, numPages]);\n\n const handleToggleOutline = useCallback(() => {\n setShowOutline(prev => !prev);\n }, []);\n\n // 工具栏配置\n const getToolbarGroups = useCallback((): ToolbarGroup[] => {\n const groups: ToolbarGroup[] = [];\n\n // 大纲按钮(如果有大纲)\n if (outline.length > 0) {\n groups.push({\n items: [\n { type: 'button', icon: <Menu className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.outline'), action: handleToggleOutline, active: showOutline },\n ],\n });\n }\n\n // 翻页\n groups.push({\n items: [\n { type: 'button', icon: <ChevronLeft className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.prev_page'), action: handlePrevPage, disabled: currentPage <= 1 },\n { type: 'text', content: `${currentPage} / ${numPages}`, minWidth: '4rem' },\n { type: 'button', icon: <ChevronRight className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.next_page'), action: handleNextPage, disabled: currentPage >= numPages },\n ],\n });\n\n // 缩放\n groups.push({\n items: [\n { type: 'button', icon: <ZoomOut className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.zoom_out'), action: handleZoomOut, disabled: zoom <= 0.5 },\n { type: 'text', content: `${Math.round(zoom * 100)}%`, minWidth: '3rem' },\n { type: 'button', icon: <ZoomIn className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.zoom_in'), action: handleZoomIn, disabled: zoom >= 3 },\n ],\n });\n\n // 重置\n groups.push({\n items: [\n { type: 'button', icon: <RefreshCw className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.reset'), action: handleReset },\n ],\n });\n\n return groups;\n }, [zoom, currentPage, numPages, showOutline, outline.length, t, handleZoomIn, handleZoomOut, handlePrevPage, handleNextPage, handleToggleOutline, handleReset]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups,\n onToolbarChange: (listener: () => void) => {\n listenersRef.current.add(listener);\n return () => listenersRef.current.delete(listener);\n },\n }), [getToolbarGroups]);\n\n return (\n <div ref={containerRef} className=\"rfp-relative rfp-w-full rfp-h-full\">\n {/* 大纲侧边栏 */}\n {outline.length > 0 && (\n <div\n className=\"rfp-absolute rfp-inset-0 rfp-z-20 rfp-flex rfp-transition-opacity rfp-duration-300\"\n style={{\n opacity: showOutline ? 1 : 0,\n pointerEvents: showOutline ? 'auto' : 'none',\n }}\n >\n <div\n className=\"rfp-w-72 rfp-max-w-[80%] rfp-h-full rfp-bg-surface-overlay rfp-backdrop-blur-xl rfp-border-r rfp-border-line-weak rfp-flex rfp-flex-col rfp-shadow-2xl rfp-transition-transform rfp-duration-300\"\n style={{ transform: showOutline ? 'translateX(0)' : 'translateX(-100%)' }}\n >\n <div className=\"rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-3 rfp-border-b rfp-border-line-weak rfp-flex-shrink-0\">\n <span className=\"rfp-text-fg-primary rfp-font-medium rfp-text-sm\">{t('toolbar.outline')}</span>\n <button\n onClick={() => setShowOutline(false)}\n className=\"rfp-text-fg-tertiary hover:rfp-text-fg-primary rfp-transition-colors\"\n >\n <X className=\"rfp-w-4 rfp-h-4\" />\n </button>\n </div>\n <div className=\"rfp-flex-1 rfp-overflow-y-auto rfp-py-4 rfp-px-1\">\n {renderOutlineItems(outline, 0, () => setShowOutline(false))}\n </div>\n </div>\n <div\n className=\"rfp-flex-1 rfp-transition-opacity rfp-duration-300\"\n style={{ background: showOutline ? 'rgba(0,0,0,0.3)' : 'transparent' }}\n onClick={() => setShowOutline(false)}\n />\n </div>\n )}\n\n <div\n ref={scrollContainerRef}\n className=\"rfp-pdf-container rfp-w-full rfp-h-full rfp-overflow-auto rfp-py-6 rfp-px-4\"\n >\n {error && (\n <RendererError message={error} />\n )}\n\n {!error && isLoading && (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-min-h-screen\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n )}\n\n {!error && (\n <div className=\"rfp-flex rfp-flex-col rfp-items-center\">\n <div className=\"pdf-pages rfp-flex rfp-flex-col rfp-gap-4\" />\n </div>\n )}\n </div>\n </div>\n );\n});\n"],"names":["PdfRenderer","forwardRef","url","ref","t","useTranslator","zoom","setZoom","useState","currentPage","setCurrentPage","numPages","setNumPages","showOutline","setShowOutline","error","setError","isLoading","setIsLoading","outline","setOutline","activeOutlineItem","setActiveOutlineItem","outlinePageMapRef","useRef","containerRef","scrollContainerRef","pdfDocRef","pageStatesRef","observerRef","listenersRef","notifyToolbarChange","useCallback","listener","useEffect","renderPage","pageNumber","scale","state","page","viewport","canvas","ctx","renderTask","err","clearPageCanvas","buildOutlinePageMap","items","pdfDoc","depth","i","item","itemKey","dest","namedDest","_a","_b","_c","updateActiveOutlineByPage","closestItem","closestDistance","itemPage","distance","initPagePlaceholders","wrapper","pageDiv","loadPdf","loadingTask","pdfjsLib","total","outlineData","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","rect","containerRect","pageCenter","entries","entry","timer","handleOutlineClick","onClose","pageRef","targetPage","renderOutlineItems","jsx","handleZoomIn","z","handleZoomOut","handleReset","handlePrevPage","handleNextPage","pages","handleToggleOutline","prev","getToolbarGroups","groups","Menu","ChevronLeft","ChevronRight","ZoomOut","ZoomIn","RefreshCw","useImperativeHandle","jsxs","X","RendererError"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as r, jsxs as t, Fragment as E } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as R, useState as m, useEffect as T, useMemo as k, useImperativeHandle as F } from "react";
|
|
3
|
-
import { u as S, a as _, T as $, P as o, z as j } from "./index-
|
|
3
|
+
import { u as S, a as _, T as $, P as o, z as j } from "./index-B3jtj_7-.mjs";
|
|
4
4
|
import { R as A } from "./RendererError-D5i8eSpN.mjs";
|
|
5
5
|
const L = {
|
|
6
6
|
srt: "srt",
|
|
@@ -101,4 +101,4 @@ const L = {
|
|
|
101
101
|
export {
|
|
102
102
|
B as SubtitleRenderer
|
|
103
103
|
};
|
|
104
|
-
//# sourceMappingURL=index-
|
|
104
|
+
//# sourceMappingURL=index-CwCdx6Io.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Bn0NJNzq.mjs","sources":["../../src/renderers/Subtitle/index.tsx"],"sourcesContent":["import { useState, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface SubtitleRendererProps {\n url: string;\n fileName: string;\n}\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nexport const SubtitleRenderer = forwardRef<RendererHandle, SubtitleRendererProps>(({ url, fileName }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [text, setText] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n setText(await fetchTextUtf8(url, { fetcher, signal: controller.signal }));\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n console.warn('[SubtitleRenderer] Failed to load subtitle:', err instanceof Error ? err.message : String(err));\n setError(t('subtitle.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n return () => controller.abort();\n }, [url]);\n\n const parsed: SubtitleParseResult | null = useMemo(() => {\n if (!text) return null;\n try {\n return parseSubtitle(text, getFormat(fileName));\n } catch (err) {\n // 字幕解析失败通常是格式不支持或文件损坏,用 warn 级别记录\n console.warn('[SubtitleRenderer] Failed to parse subtitle:', err instanceof Error ? err.message : String(err));\n return null;\n }\n }, [text, fileName]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error || !parsed) {\n return <RendererError message={error || t('subtitle.parse_failed')} />;\n }\n\n const isLyric = parsed.format === 'lrc' || parsed.format === 'elrc';\n const meta = parsed.metadata ?? {};\n const dotHover = isLyric ? 'group-hover:rfp-bg-violet-400' : 'group-hover:rfp-bg-sky-400';\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n {/* 内容滚动区 */}\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-px-4 rfp-pt-6 rfp-pb-16\">\n <div className=\"rfp-relative\">\n {/* vertical line */}\n <div className=\"rfp-absolute rfp-left-[5px] rfp-top-2 rfp-bottom-2 rfp-w-px rfp-bg-surface-1\" />\n\n <ol className=\"rfp-space-y-5\">\n {parsed.cues.map((cue, i) => (\n <li key={`cue-${i}`} className=\"rfp-relative rfp-pl-6 rfp-group\">\n {/* dot */}\n <div\n className={`rfp-absolute rfp-left-0 rfp-top-[0.4rem] rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${dotHover}`}\n />\n\n <div className=\"rfp-flex rfp-flex-wrap rfp-items-baseline rfp-gap-x-3 rfp-gap-y-1 rfp-mb-1.5\">\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.start)}\n </span>\n <span className=\"rfp-text-[11px] rfp-text-fg-disabled\">→</span>\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.end)}\n </span>\n <span className=\"rfp-text-[10px] rfp-font-mono rfp-text-fg-disabled rfp-tabular-nums\">\n #{cue.id ?? i + 1}\n </span>\n {cue.style && (\n <span className=\"rfp-text-[9px] rfp-uppercase rfp-tracking-widest rfp-text-fg-tertiary rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-bg-surface-1 rfp-border rfp-border-line-weak\">\n {cue.style}\n </span>\n )}\n </div>\n\n {cue.words && cue.words.length > 0 ? (\n <div className=\"rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors\">\n {cue.words.map((word, wi) => (\n <span\n key={`w-${wi}`}\n className=\"rfp-inline-flex rfp-flex-col rfp-items-start\"\n title={formatSubtitleTime(word.start)}\n >\n <span className=\"rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums\">\n {formatSubtitleTime(word.start).slice(3, 8)}\n </span>\n <span className=\"rfp-leading-snug\">{word.text}</span>\n </span>\n ))}\n </div>\n ) : (\n <p\n className={`rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary rfp-min-h-[1.25rem] ${\n isLyric ? 'rfp-text-base rfp-font-medium' : 'rfp-text-sm'\n }`}\n >\n {cue.text}\n </p>\n )}\n </li>\n ))}\n </ol>\n </div>\n </div>\n\n {/* 底部状态栏 */}\n <div className=\"rfp-pointer-events-none rfp-absolute rfp-bottom-3 rfp-right-3 rfp-flex rfp-items-center rfp-gap-2 rfp-px-2.5 rfp-py-1 rfp-rounded-full rfp-bg-surface-nav rfp-backdrop-blur rfp-border rfp-border-line-weak rfp-text-[10px] rfp-text-fg-tertiary rfp-font-mono rfp-tabular-nums\">\n <span>{parsed.cues.length} {isLyric ? t('subtitle.lines') : t('subtitle.cues')}</span>\n {meta.length && (\n <>\n <span className=\"rfp-text-fg-disabled\">·</span>\n <span>{meta.length}</span>\n </>\n )}\n </div>\n </div>\n );\n});\n"],"names":["FORMAT_BY_EXT","getFormat","fileName","ext","_a","SubtitleRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","text","setText","useState","loading","setLoading","error","setError","useEffect","controller","fetchTextUtf8","err","parsed","useMemo","parseSubtitle","useImperativeHandle","jsx","RendererError","isLyric","meta","dotHover","jsxs","cue","i","formatSubtitleTime","word","wi","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CwCdx6Io.mjs","sources":["../../src/renderers/Subtitle/index.tsx"],"sourcesContent":["import { useState, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface SubtitleRendererProps {\n url: string;\n fileName: string;\n}\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nexport const SubtitleRenderer = forwardRef<RendererHandle, SubtitleRendererProps>(({ url, fileName }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [text, setText] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n setText(await fetchTextUtf8(url, { fetcher, signal: controller.signal }));\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n console.warn('[SubtitleRenderer] Failed to load subtitle:', err instanceof Error ? err.message : String(err));\n setError(t('subtitle.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n return () => controller.abort();\n }, [url]);\n\n const parsed: SubtitleParseResult | null = useMemo(() => {\n if (!text) return null;\n try {\n return parseSubtitle(text, getFormat(fileName));\n } catch (err) {\n // 字幕解析失败通常是格式不支持或文件损坏,用 warn 级别记录\n console.warn('[SubtitleRenderer] Failed to parse subtitle:', err instanceof Error ? err.message : String(err));\n return null;\n }\n }, [text, fileName]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error || !parsed) {\n return <RendererError message={error || t('subtitle.parse_failed')} />;\n }\n\n const isLyric = parsed.format === 'lrc' || parsed.format === 'elrc';\n const meta = parsed.metadata ?? {};\n const dotHover = isLyric ? 'group-hover:rfp-bg-violet-400' : 'group-hover:rfp-bg-sky-400';\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n {/* 内容滚动区 */}\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-px-4 rfp-pt-6 rfp-pb-16\">\n <div className=\"rfp-relative\">\n {/* vertical line */}\n <div className=\"rfp-absolute rfp-left-[5px] rfp-top-2 rfp-bottom-2 rfp-w-px rfp-bg-surface-1\" />\n\n <ol className=\"rfp-space-y-5\">\n {parsed.cues.map((cue, i) => (\n <li key={`cue-${i}`} className=\"rfp-relative rfp-pl-6 rfp-group\">\n {/* dot */}\n <div\n className={`rfp-absolute rfp-left-0 rfp-top-[0.4rem] rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${dotHover}`}\n />\n\n <div className=\"rfp-flex rfp-flex-wrap rfp-items-baseline rfp-gap-x-3 rfp-gap-y-1 rfp-mb-1.5\">\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.start)}\n </span>\n <span className=\"rfp-text-[11px] rfp-text-fg-disabled\">→</span>\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.end)}\n </span>\n <span className=\"rfp-text-[10px] rfp-font-mono rfp-text-fg-disabled rfp-tabular-nums\">\n #{cue.id ?? i + 1}\n </span>\n {cue.style && (\n <span className=\"rfp-text-[9px] rfp-uppercase rfp-tracking-widest rfp-text-fg-tertiary rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-bg-surface-1 rfp-border rfp-border-line-weak\">\n {cue.style}\n </span>\n )}\n </div>\n\n {cue.words && cue.words.length > 0 ? (\n <div className=\"rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors\">\n {cue.words.map((word, wi) => (\n <span\n key={`w-${wi}`}\n className=\"rfp-inline-flex rfp-flex-col rfp-items-start\"\n title={formatSubtitleTime(word.start)}\n >\n <span className=\"rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums\">\n {formatSubtitleTime(word.start).slice(3, 8)}\n </span>\n <span className=\"rfp-leading-snug\">{word.text}</span>\n </span>\n ))}\n </div>\n ) : (\n <p\n className={`rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary rfp-min-h-[1.25rem] ${\n isLyric ? 'rfp-text-base rfp-font-medium' : 'rfp-text-sm'\n }`}\n >\n {cue.text}\n </p>\n )}\n </li>\n ))}\n </ol>\n </div>\n </div>\n\n {/* 底部状态栏 */}\n <div className=\"rfp-pointer-events-none rfp-absolute rfp-bottom-3 rfp-right-3 rfp-flex rfp-items-center rfp-gap-2 rfp-px-2.5 rfp-py-1 rfp-rounded-full rfp-bg-surface-nav rfp-backdrop-blur rfp-border rfp-border-line-weak rfp-text-[10px] rfp-text-fg-tertiary rfp-font-mono rfp-tabular-nums\">\n <span>{parsed.cues.length} {isLyric ? t('subtitle.lines') : t('subtitle.cues')}</span>\n {meta.length && (\n <>\n <span className=\"rfp-text-fg-disabled\">·</span>\n <span>{meta.length}</span>\n </>\n )}\n </div>\n </div>\n );\n});\n"],"names":["FORMAT_BY_EXT","getFormat","fileName","ext","_a","SubtitleRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","text","setText","useState","loading","setLoading","error","setError","useEffect","controller","fetchTextUtf8","err","parsed","useMemo","parseSubtitle","useImperativeHandle","jsx","RendererError","isLyric","meta","dotHover","jsxs","cue","i","formatSubtitleTime","word","wi","Fragment"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as r, jsxs as w } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as b, useState as d, useEffect as N, useImperativeHandle as y, Fragment as x } from "react";
|
|
3
|
-
import { u as v, a as z, z as S } from "./index-
|
|
4
|
-
import { u as $ } from "./useShikiHighlight-
|
|
3
|
+
import { u as v, a as z, z as S } from "./index-B3jtj_7-.mjs";
|
|
4
|
+
import { u as $ } from "./useShikiHighlight-DHhZ6Oy9.mjs";
|
|
5
5
|
import { R } from "./RendererError-D5i8eSpN.mjs";
|
|
6
6
|
const T = (t) => {
|
|
7
7
|
try {
|
|
@@ -75,4 +75,4 @@ $2$3`), e = 0;
|
|
|
75
75
|
export {
|
|
76
76
|
k as XmlRenderer
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=index-
|
|
78
|
+
//# sourceMappingURL=index-D3Wso9Iz.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-D3Wso9Iz.mjs","sources":["../../src/renderers/Xml/index.tsx"],"sourcesContent":["import { useState, useEffect, Fragment, forwardRef, useImperativeHandle } from 'react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useShikiHighlight } from '../../hooks/useShikiHighlight';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface XmlRendererProps {\n url: string;\n fileName: string;\n}\n\n/**\n * 用 DOMParser 美化 XML:失败则原样返回\n */\nconst prettyPrintXml = (xml: string): string => {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, 'application/xml');\n // 检测解析错误\n const errNode = doc.querySelector('parsererror');\n if (errNode) return xml;\n // 使用 XSLT 或手动缩进:这里手动缩进更稳\n const serializer = new XMLSerializer();\n const serialized = serializer.serializeToString(doc);\n return indentXml(serialized);\n } catch {\n return xml;\n }\n};\n\nconst indentXml = (xml: string): string => {\n const PADDING = ' ';\n const reg = /(>)(<)(\\/*)/g;\n let formatted = xml.replace(reg, '$1\\n$2$3');\n // 自闭合和 CDATA 等不处理\n let pad = 0;\n return formatted\n .split('\\n')\n .map((line) => {\n let indent = 0;\n if (/^<\\/\\w/.test(line)) {\n pad = Math.max(pad - 1, 0);\n } else if (/^<\\w[^>]*[^/]>.*$/.test(line) && !/<.+<\\/.+>$/.test(line)) {\n indent = 1;\n }\n const padded = PADDING.repeat(pad) + line;\n pad += indent;\n return padded;\n })\n .join('\\n');\n};\n\nexport const XmlRenderer = forwardRef<RendererHandle, XmlRendererProps>(({ url }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const { lineHtmls } = useShikiHighlight(content, 'xml');\n\n useEffect(() => {\n const controller = new AbortController();\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n const raw = await fetchTextUtf8(url, { fetcher, signal: controller.signal });\n setContent(prettyPrintXml(raw));\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n console.error(err);\n setError(t('xml.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n return () => controller.abort();\n }, [url]);\n\n // 暴露接口给父组件(必须在 early return 之前调用)\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return <RendererError message={error} />;\n }\n\n if (lineHtmls.length === 0) {\n return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg\">\n <pre className=\"rfp-py-6 rfp-px-4 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words\">\n {content}\n </pre>\n </div>\n );\n }\n\n const lines = content.split('\\n');\n return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg\">\n <div\n className=\"rfp-code-block with-line-numbers rfp-w-full\"\n style={{ gridTemplateRows: `repeat(${lines.length}, auto) minmax(1.5rem, 1fr)` }}\n >\n {lines.map((_, i) => (\n <Fragment key={i}>\n <span className=\"rfp-code-gutter\">{i + 1}</span>\n <span\n className=\"rfp-code-line\"\n dangerouslySetInnerHTML={{ __html: lineHtmls[i] ?? '' }}\n />\n </Fragment>\n ))}\n {/* 占位行:撑满剩余高度,让 gutter border 延伸到底部 */}\n <span className=\"rfp-code-gutter-filler\" />\n <span className=\"rfp-code-line-filler\" />\n </div>\n </div>\n );\n});\n"],"names":["prettyPrintXml","xml","doc","serialized","indentXml","PADDING","reg","formatted","pad","line","indent","padded","XmlRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","content","setContent","useState","loading","setLoading","error","setError","lineHtmls","useShikiHighlight","useEffect","controller","raw","fetchTextUtf8","err","useImperativeHandle","jsx","RendererError","lines","jsxs","_","i","Fragment"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as L, jsx as m } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as F, useState as M, useRef as l, useCallback as P, useEffect as j, useImperativeHandle as H } from "react";
|
|
3
3
|
import { init as N } from "pptx-preview";
|
|
4
|
-
import { u as I, a as q } from "./index-
|
|
4
|
+
import { u as I, a as q } from "./index-B3jtj_7-.mjs";
|
|
5
5
|
import { R as A } from "./RendererError-D5i8eSpN.mjs";
|
|
6
6
|
const K = F(({ url: y, tiled: a = !0 }, k) => {
|
|
7
7
|
const c = I(), B = q(), [b, w] = M(!0), [v, T] = M(null), [E, z] = M(0), n = l(null), s = l(null), x = l(null), p = l(null), d = l(null), R = l({ width: 0, height: 0 }), u = P(() => {
|
|
@@ -135,4 +135,4 @@ const K = F(({ url: y, tiled: a = !0 }, k) => {
|
|
|
135
135
|
export {
|
|
136
136
|
K as PptxRenderer
|
|
137
137
|
};
|
|
138
|
-
//# sourceMappingURL=index-
|
|
138
|
+
//# sourceMappingURL=index-DXZFI5Vp.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-VnjkEX5p.mjs","sources":["../../src/renderers/Pptx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface PptxRendererProps {\n url: string;\n /** 是否平铺展示所有页面,默认 true */\n tiled?: boolean;\n}\n\nexport const PptxRenderer = forwardRef<RendererHandle, PptxRendererProps>(({ url, tiled = true }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [slideCount, setSlideCount] = useState(0);\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 const rawWidth = containerRef.current.clientWidth;\n const parentWidth = containerRef.current.parentElement?.clientWidth || 0;\n // 如果容器宽度太小,回退到父容器宽度或默认最小值\n const containerWidth = rawWidth > 100 ? rawWidth : (parentWidth > 100 ? parentWidth : 300);\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current || slideCount === 0) return;\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n\n // 初始化新的预览器,平铺模式下高度按页数计算\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * slideCount : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n } catch {\n // 重新初始化失败,静默处理\n }\n }, [calculateDimensions, tiled, slideCount]);\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 lastDimensionsRef.current = calculateDimensions();\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 return;\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 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 // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!url) return;\n\n let isMounted = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const loadPptx = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n // 设置30秒超时\n timeoutId = setTimeout(() => {\n if (isMounted) {\n setError(t('pptx.timeout'));\n setLoading(false);\n }\n }, 30000);\n\n try {\n // 获取文件,处理 CORS 和重定向\n const response = await fetcher(url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(t('pptx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else if (response.status >= 500) {\n throw new Error('服务器错误,请稍后重试');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // 验证文件大小\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n arrayBufferRef.current = arrayBuffer;\n\n if (!isMounted) return;\n\n // 步骤 1: 创建隐藏容器,预处理获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n // 在隐藏容器中初始化临时预览器获取页数\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n\n if (!count || count === 0) {\n throw new Error(t('pptx.no_pages'));\n }\n\n // 销毁临时预览器\n tempPreviewer.destroy();\n\n if (!isMounted) return;\n\n // 保存 slideCount\n setSlideCount(count);\n\n // 步骤 2: 清空真实容器并初始化\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n\n // 步骤 3: 初始化真实预览器,平铺模式下使用正确的总高度\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 步骤 4: 预览 PPTX\n await previewer.preview(arrayBuffer);\n\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n setLoading(false);\n }\n } finally {\n // 移除隐藏容器\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n let errorMsg = t('pptx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n } else if (typeof err === 'string') {\n errorMsg = err;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n // 延迟执行,使用 requestAnimationFrame 确保 DOM 已准备好\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n loadPptx();\n });\n });\n }, 150);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n arrayBufferRef.current = null;\n setSlideCount(0);\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions, tiled]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('pptx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && !loading && (\n <RendererError message={t('pptx.load_failed')} detail={error} />\n )}\n\n {/* PPT 容器 - 仅在非错误状态下渲染 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"pptx-wrapper rfp-w-full rfp-max-w-full md:rfp-max-w-6xl\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n});\n"],"names":["PptxRenderer","forwardRef","url","tiled","ref","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","slideCount","setSlideCount","containerRef","useRef","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","timeoutId","loadPptx","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","timer","useImperativeHandle","jsxs","jsx","RendererError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-DXZFI5Vp.mjs","sources":["../../src/renderers/Pptx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface PptxRendererProps {\n url: string;\n /** 是否平铺展示所有页面,默认 true */\n tiled?: boolean;\n}\n\nexport const PptxRenderer = forwardRef<RendererHandle, PptxRendererProps>(({ url, tiled = true }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [slideCount, setSlideCount] = useState(0);\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 const rawWidth = containerRef.current.clientWidth;\n const parentWidth = containerRef.current.parentElement?.clientWidth || 0;\n // 如果容器宽度太小,回退到父容器宽度或默认最小值\n const containerWidth = rawWidth > 100 ? rawWidth : (parentWidth > 100 ? parentWidth : 300);\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current || slideCount === 0) return;\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n\n // 初始化新的预览器,平铺模式下高度按页数计算\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * slideCount : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n } catch {\n // 重新初始化失败,静默处理\n }\n }, [calculateDimensions, tiled, slideCount]);\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 lastDimensionsRef.current = calculateDimensions();\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 return;\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 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 // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!url) return;\n\n let isMounted = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const loadPptx = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n // 设置30秒超时\n timeoutId = setTimeout(() => {\n if (isMounted) {\n setError(t('pptx.timeout'));\n setLoading(false);\n }\n }, 30000);\n\n try {\n // 获取文件,处理 CORS 和重定向\n const response = await fetcher(url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(t('pptx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else if (response.status >= 500) {\n throw new Error('服务器错误,请稍后重试');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // 验证文件大小\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n arrayBufferRef.current = arrayBuffer;\n\n if (!isMounted) return;\n\n // 步骤 1: 创建隐藏容器,预处理获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n // 在隐藏容器中初始化临时预览器获取页数\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n\n if (!count || count === 0) {\n throw new Error(t('pptx.no_pages'));\n }\n\n // 销毁临时预览器\n tempPreviewer.destroy();\n\n if (!isMounted) return;\n\n // 保存 slideCount\n setSlideCount(count);\n\n // 步骤 2: 清空真实容器并初始化\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n\n // 步骤 3: 初始化真实预览器,平铺模式下使用正确的总高度\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 步骤 4: 预览 PPTX\n await previewer.preview(arrayBuffer);\n\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n setLoading(false);\n }\n } finally {\n // 移除隐藏容器\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n let errorMsg = t('pptx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n } else if (typeof err === 'string') {\n errorMsg = err;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n // 延迟执行,使用 requestAnimationFrame 确保 DOM 已准备好\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n loadPptx();\n });\n });\n }, 150);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n arrayBufferRef.current = null;\n setSlideCount(0);\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions, tiled]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('pptx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && !loading && (\n <RendererError message={t('pptx.load_failed')} detail={error} />\n )}\n\n {/* PPT 容器 - 仅在非错误状态下渲染 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"pptx-wrapper rfp-w-full rfp-max-w-full md:rfp-max-w-6xl\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n});\n"],"names":["PptxRenderer","forwardRef","url","tiled","ref","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","slideCount","setSlideCount","containerRef","useRef","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","timeoutId","loadPptx","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","timer","useImperativeHandle","jsxs","jsx","RendererError"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as k, jsxs as L, Fragment as Z } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as S, useMemo as h, useState as E, useEffect as x, useImperativeHandle as P, useCallback as K } from "react";
|
|
3
3
|
import { ChevronDown as C, ChevronRight as ee } from "lucide-react";
|
|
4
|
-
import { u as W, a as ne, b as te, z as le } from "./index-
|
|
4
|
+
import { u as W, a as ne, b as te, z as le } from "./index-B3jtj_7-.mjs";
|
|
5
5
|
import { R as ie } from "./RendererError-D5i8eSpN.mjs";
|
|
6
6
|
function fe(e, u = !1) {
|
|
7
7
|
const p = e.length;
|
|
@@ -593,4 +593,4 @@ const we = S(({ url: e }, u) => {
|
|
|
593
593
|
export {
|
|
594
594
|
we as JsonRenderer
|
|
595
595
|
};
|
|
596
|
-
//# sourceMappingURL=index-
|
|
596
|
+
//# sourceMappingURL=index-DZC5bucC.mjs.map
|