@turinhub/atomix-common-ui 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AuthPanel-CTKx618F.cjs +2 -0
- package/dist/AuthPanel-CTKx618F.cjs.map +1 -0
- package/dist/{AuthPanel-D2HFX8eN.js → AuthPanel-Cn_WwmjX.js} +259 -212
- package/dist/AuthPanel-Cn_WwmjX.js.map +1 -0
- package/dist/PDFSidebar-4DtXqqzN.cjs +2 -0
- package/dist/PDFSidebar-4DtXqqzN.cjs.map +1 -0
- package/dist/PDFSidebar-ClnrF4Br.js +239 -0
- package/dist/PDFSidebar-ClnrF4Br.js.map +1 -0
- package/dist/auth.cjs +1 -1
- package/dist/auth.js +1 -1
- package/dist/components/AuthLoginPanel.d.ts.map +1 -1
- package/dist/components/AuthRegisterPanel.d.ts.map +1 -1
- package/dist/components/AuthVisualCarousel.d.ts +2 -0
- package/dist/components/AuthVisualCarousel.d.ts.map +1 -1
- package/dist/components/DataTable.d.ts.map +1 -1
- package/dist/components/ImageReader.d.ts.map +1 -1
- package/dist/components/MarkdownReader.d.ts.map +1 -1
- package/dist/components/PDFReader.d.ts.map +1 -1
- package/dist/components/PDFSidebar.d.ts.map +1 -1
- package/dist/components/SimplePDFReader.d.ts.map +1 -1
- package/dist/components/TableHeader.d.ts.map +1 -1
- package/dist/components/TablePagination.d.ts +2 -1
- package/dist/components/TablePagination.d.ts.map +1 -1
- package/dist/components/VideoReader.d.ts.map +1 -1
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/data-table.cjs.map +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/file-upload.cjs +1 -1
- package/dist/file-upload.cjs.map +1 -1
- package/dist/file-upload.js +36 -36
- package/dist/file-upload.js.map +1 -1
- package/dist/image-reader.cjs +1 -1
- package/dist/image-reader.cjs.map +1 -1
- package/dist/image-reader.js +1 -0
- package/dist/image-reader.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/markdown-reader.cjs +1 -1
- package/dist/markdown-reader.cjs.map +1 -1
- package/dist/markdown-reader.js +28 -24
- package/dist/markdown-reader.js.map +1 -1
- package/dist/pdf-reader.cjs +1 -1
- package/dist/pdf-reader.cjs.map +1 -1
- package/dist/pdf-reader.js +169 -120
- package/dist/pdf-reader.js.map +1 -1
- package/dist/pdf-sidebar.cjs +1 -1
- package/dist/pdf-sidebar.js +1 -1
- package/dist/simple-pdf-reader.cjs +1 -1
- package/dist/simple-pdf-reader.cjs.map +1 -1
- package/dist/simple-pdf-reader.js +137 -104
- package/dist/simple-pdf-reader.js.map +1 -1
- package/dist/table-header.cjs +1 -1
- package/dist/table-header.cjs.map +1 -1
- package/dist/table-header.js +42 -34
- package/dist/table-header.js.map +1 -1
- package/dist/table-pagination.cjs +1 -1
- package/dist/table-pagination.cjs.map +1 -1
- package/dist/table-pagination.js +49 -43
- package/dist/table-pagination.js.map +1 -1
- package/dist/types/component-types.d.ts +1 -0
- package/dist/types/component-types.d.ts.map +1 -1
- package/dist/video-reader.cjs.map +1 -1
- package/dist/video-reader.js.map +1 -1
- package/package.json +2 -1
- package/dist/AuthPanel-C_2JBE7t.cjs +0 -2
- package/dist/AuthPanel-C_2JBE7t.cjs.map +0 -1
- package/dist/AuthPanel-D2HFX8eN.js.map +0 -1
- package/dist/PDFSidebar-BBtucLK6.js +0 -232
- package/dist/PDFSidebar-BBtucLK6.js.map +0 -1
- package/dist/PDFSidebar-Di0D-yPS.cjs +0 -2
- package/dist/PDFSidebar-Di0D-yPS.cjs.map +0 -1
package/dist/pdf-reader.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-reader.cjs","sources":["../src/components/PDFReader.tsx"],"sourcesContent":["import {\n ChevronLeft as ChevronLeftIcon,\n ChevronRight as ChevronRightIcon,\n FileText as FileTextIcon,\n Maximize2 as Maximize2Icon,\n Minimize2 as Minimize2Icon,\n PanelLeft as PanelLeftIcon,\n RotateCw as RotateCwIcon,\n ScrollText as ScrollTextIcon,\n ZoomIn as ZoomInIcon,\n ZoomOut as ZoomOutIcon,\n} from 'lucide-react';\nimport { useState, useCallback, useEffect, useMemo, useRef } from 'react';\nimport type { HTMLAttributes } from 'react';\n\nimport type {\n CardComponent,\n ButtonComponent,\n InputComponent,\n SkeletonComponent,\n} from '../types/component-types';\n\nimport type { PDFDocumentProxy } from './PDFSidebar';\nimport { PDFSidebar } from './PDFSidebar';\n\n/**\n * PDFReader UI 组件接口\n */\nexport interface PDFReaderUIComponents {\n /** Card 组件 (必需) */\n Card: CardComponent;\n /** CardContent 组件 (必需) */\n CardContent: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n /** Button 组件 (必需) */\n Button: ButtonComponent;\n /** Input 组件 (必需) */\n Input: InputComponent;\n /** Skeleton 组件 (必需) */\n Skeleton: SkeletonComponent;\n /** Tabs 组件 (showSidebar=true 时必需) */\n Tabs?: React.ComponentType<{\n value?: string;\n onValueChange?: (value: string) => void;\n children?: React.ReactNode;\n defaultValue?: string;\n }>;\n /** TabsList 组件 (showSidebar=true 时必需) */\n TabsList?: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n /** TabsTrigger 组件 (showSidebar=true 时必需) */\n TabsTrigger?: React.ComponentType<{\n value: string;\n children?: React.ReactNode;\n }>;\n /** TabsContent 组件 (showSidebar=true 时必需) */\n TabsContent?: React.ComponentType<{\n value: string;\n children?: React.ReactNode;\n }>;\n /** ScrollArea 组件 (showSidebar=true 时必需) */\n ScrollArea?: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n}\n\n/**\n * PDFReader 组件 Props\n */\nexport interface PDFReaderProps {\n // ==================== 基础配置 ====================\n /** PDF 文件 URL (必需) */\n url: string;\n\n // ==================== 初始状态 ====================\n /** 初始页码 (默认 1) */\n initialPage?: number;\n /** 初始缩放比例 (默认 1.0) */\n initialScale?: number;\n /** 初始旋转角度 (默认 0) */\n initialRotation?: number;\n\n // ==================== 受控模式 ====================\n /** 当前页码 (受控) */\n currentPage?: number;\n /** 页码变化回调 */\n onPageChange?: (page: number) => void;\n /** 缩放比例 (受控) */\n scale?: number;\n /** 缩放变化回调 */\n onScaleChange?: (scale: number) => void;\n /** 旋转角度 (受控) */\n rotation?: number;\n /** 旋转变化回调 */\n onRotationChange?: (rotation: number) => void;\n\n // ==================== 缩放限制 ====================\n /** 最小缩放比例 (默认 0.5) */\n minScale?: number;\n /** 最大缩放比例 (默认 2.5) */\n maxScale?: number;\n\n // ==================== 功能开关 ====================\n /** 显示工具栏 (默认 true) */\n showToolbar?: boolean;\n /** 显示侧边栏 (默认 true) */\n showSidebar?: boolean;\n /** 显示旋转按钮 (默认 true) */\n showRotation?: boolean;\n /** 显示模式切换按钮 (默认 true) */\n showModeToggle?: boolean;\n /** 显示全屏按钮 (默认 true) */\n showFullscreen?: boolean;\n /** 启用键盘快捷键 (默认 true) */\n enableHotkeys?: boolean;\n /** 启用移动端导航 (默认 true) */\n enableMobileNav?: boolean;\n\n // ==================== 显示模式 ====================\n /** 显示模式: 'scroll' 显示所有页面, 'single' 单页模式 (默认 'single') */\n displayMode?: 'scroll' | 'single';\n\n // ==================== 样式定制 ====================\n /** 容器类名 */\n className?: string;\n /** 工具栏类名 */\n toolbarClassName?: string;\n /** 内容区域类名 */\n contentClassName?: string;\n /** 阅读区域高度限制 (默认 '80vh') */\n contentHeight?: string | number;\n /** 页面类名 */\n pageClassName?: string;\n\n // ==================== Worker 配置 ====================\n /** Worker 文件 URL (可选,默认使用 CDN) */\n workerUrl?: string;\n /** CMap 文件 URL (可选,默认使用 CDN) */\n cMapUrl?: string;\n /** 标准字体数据 URL (可选,默认使用 CDN) */\n standardFontDataUrl?: string;\n\n // ==================== UI 组件注入 ====================\n /** UI 组件 */\n components: PDFReaderUIComponents;\n\n // ==================== 回调函数 ====================\n /** 加载成功回调 */\n onLoadSuccess?: (pdf: PDFDocumentProxy) => void;\n /** 加载错误回调 */\n onLoadError?: (error: Error) => void;\n /** 页面渲染回调 */\n onPageRender?: (pageIndex: number) => void;\n\n // ==================== 文本配置 ====================\n /** 加载文本 (默认 '正在加载PDF文档...') */\n loadingText?: string;\n /** 错误文本 (默认 'PDF加载失败') */\n errorText?: string;\n}\n\n/**\n * debounce hook (替代 lodash.debounce)\n */\nfunction useDebounce<T extends (...args: any[]) => any>(\n callback: T,\n delay: number\n): T {\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(\n undefined\n );\n return useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => callback(...args), delay);\n },\n [callback, delay]\n ) as T;\n}\n\n/**\n * PDFReader 组件\n *\n * 功能完整的 PDF 阅读器组件,支持侧边栏导航、页面旋转、显示模式切换等高级特性。\n *\n * @example\n * ```tsx\n * import { PDFReader } from '@turinhub/atomix-common-ui/pdf-reader';\n * import { Card, Button, Input, Label, Skeleton } from '@/components/ui';\n * import { Tabs, ScrollArea } from '@/components/ui';\n *\n * <PDFReader\n * url=\"/documents/sample.pdf\"\n * components={{\n * Card,\n * CardContent: Card.Content,\n * Button,\n * Input,\n * Label,\n * Skeleton,\n * Tabs,\n * TabsList: Tabs.List,\n * TabsTrigger: Tabs.Trigger,\n * TabsContent: Tabs.Content,\n * ScrollArea,\n * }}\n * initialPage={1}\n * initialScale={1.0}\n * showSidebar={true}\n * showRotation={true}\n * showModeToggle={true}\n * enableHotkeys={true}\n * />\n * ```\n */\nexport function PDFReader({\n url,\n initialPage = 1,\n initialScale = 1.0,\n initialRotation = 0,\n currentPage: controlledPage,\n onPageChange,\n scale: controlledScale,\n onScaleChange,\n rotation: controlledRotation,\n onRotationChange,\n minScale = 0.5,\n maxScale = 2.5,\n showToolbar = true,\n showSidebar = true,\n showRotation = true,\n showModeToggle = true,\n showFullscreen = true,\n enableHotkeys = true,\n enableMobileNav = true,\n displayMode: initialDisplayMode = 'single',\n className,\n toolbarClassName,\n contentClassName,\n contentHeight = '80vh',\n pageClassName,\n workerUrl,\n cMapUrl,\n standardFontDataUrl,\n components,\n onLoadSuccess,\n onLoadError,\n onPageRender,\n loadingText = '正在加载PDF文档...',\n errorText = 'PDF加载失败',\n}: PDFReaderProps) {\n // ==================== 状态管理 ====================\n const [pdfDocument, setPdfDocument] = useState<PDFDocumentProxy | null>(null);\n const [internalPage, setInternalPage] = useState(initialPage);\n const [internalScale, setInternalScale] = useState(initialScale);\n const [internalRotation, setInternalRotation] = useState(initialRotation);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [totalPages, setTotalPages] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showAllPages, setShowAllPages] = useState(\n initialDisplayMode === 'scroll'\n );\n const [showSidebarState, setShowSidebarState] = useState(showSidebar);\n\n // Sync showSidebarState with prop changes\n useEffect(() => {\n setShowSidebarState(showSidebar);\n }, [showSidebar]);\n\n const [pageWidth, setPageWidth] = useState<number | undefined>(undefined);\n\n // 动态导入 react-pdf\n const [ReactPDF, setReactPDF] = useState<any>(null);\n\n const readerRef = useRef<HTMLDivElement>(null);\n const pdfContainerRef = useRef<HTMLDivElement>(null);\n const pageRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n // 使用受控或非受控模式\n const currentPage = controlledPage ?? internalPage;\n const scale = controlledScale ?? internalScale;\n const rotation = controlledRotation ?? internalRotation;\n const isPageControlled = controlledPage !== undefined;\n const isScrollMode = showAllPages;\n\n // ==================== 组件解构 ====================\n const { Card, CardContent, Button, Input, Skeleton } = components || {};\n\n useEffect(() => {\n setPdfDocument(null);\n setTotalPages(0);\n setError(null);\n setIsLoading(false);\n if (!isPageControlled) {\n setInternalPage(Math.max(1, initialPage));\n }\n }, [url, initialPage, isPageControlled]);\n\n // ==================== PDF 选项 ====================\n const pdfOptions = useMemo(() => {\n const options: Record<string, unknown> = {\n withCredentials: false,\n };\n\n if (cMapUrl) {\n options.cMapUrl = cMapUrl;\n options.cMapPacked = true;\n }\n\n if (standardFontDataUrl) {\n options.standardFontDataUrl = standardFontDataUrl;\n }\n\n return options;\n }, [cMapUrl, standardFontDataUrl]);\n\n // ==================== 动态导入 react-pdf ====================\n useEffect(() => {\n let isMounted = true;\n\n const loadReactPDF = async () => {\n try {\n // 动态导入 react-pdf\n const pdfModule = await import('react-pdf');\n\n // 设置 worker\n if (typeof window !== 'undefined') {\n const pdfjs = (pdfModule as any).pdfjs;\n const workerVersion = pdfjs?.version;\n\n if (pdfjs?.GlobalWorkerOptions && workerVersion) {\n if (workerUrl) {\n pdfjs.GlobalWorkerOptions.workerSrc = workerUrl;\n } else {\n // 使用 CDN\n pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${workerVersion}/build/pdf.worker.min.mjs`;\n }\n\n // 如果没有提供自定义 URL,使用 CDN 默认值\n if (!cMapUrl && pdfjs.GlobalWorkerOptions) {\n (pdfjs.GlobalWorkerOptions as any).cMapUrl =\n `https://unpkg.com/pdfjs-dist@${workerVersion}/cmaps/`;\n }\n if (!standardFontDataUrl && pdfjs.GlobalWorkerOptions) {\n (pdfjs.GlobalWorkerOptions as any).standardFontDataUrl =\n `https://unpkg.com/pdfjs-dist@${workerVersion}/standard_fonts/`;\n }\n }\n }\n\n if (isMounted) {\n setReactPDF(pdfModule);\n }\n } catch (err) {\n if (isMounted) {\n const loadError =\n err instanceof Error ? err : new Error('无法加载 react-pdf 库');\n setError(loadError);\n setIsLoading(false);\n onLoadError?.(loadError);\n }\n }\n };\n\n loadReactPDF();\n\n return () => {\n isMounted = false;\n };\n }, [workerUrl, cMapUrl, standardFontDataUrl, onLoadError]);\n\n // ==================== 处理加载错误 ====================\n const onDocumentLoadError = useCallback(\n (err: Error) => {\n console.error('PDF加载失败:', err);\n console.error('PDF URL:', url);\n setPdfDocument(null);\n setTotalPages(0);\n setError(\n new Error(`${errorText}: ${err.message || '请检查文件路径或网络连接'}`)\n );\n setIsLoading(false);\n onLoadError?.(err);\n },\n [url, errorText, onLoadError]\n );\n\n const onDocumentLoadSuccess = useCallback(\n (pdf: PDFDocumentProxy) => {\n setPdfDocument(pdf);\n setTotalPages(pdf.numPages);\n setError(null);\n setIsLoading(false);\n\n if (!isPageControlled) {\n setInternalPage((page) =>\n Math.max(1, Math.min(page, Math.max(pdf.numPages, 1)))\n );\n }\n\n onLoadSuccess?.(pdf);\n },\n [isPageControlled, onLoadSuccess]\n );\n\n // ==================== 页面导航 ====================\n const goToPage = useCallback(\n (page: number) => {\n if (!Number.isFinite(page)) return;\n const newPage =\n totalPages > 0\n ? Math.max(1, Math.min(Math.trunc(page), totalPages))\n : Math.max(1, Math.trunc(page));\n if (!isPageControlled) {\n setInternalPage(newPage);\n }\n if (newPage !== currentPage) {\n onPageChange?.(newPage);\n }\n },\n [totalPages, isPageControlled, currentPage, onPageChange]\n );\n\n const setPageRef = useCallback(\n (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 );\n\n const syncScrollModeCurrentPage = useCallback(() => {\n const container = pdfContainerRef.current;\n if (!container || !isScrollMode || totalPages <= 0) return;\n\n const containerTop = container.getBoundingClientRect().top;\n let closestPage = currentPage;\n let closestDistance = Number.POSITIVE_INFINITY;\n\n pageRefs.current.forEach((element, pageNumber) => {\n const distance = Math.abs(\n element.getBoundingClientRect().top - containerTop\n );\n if (distance < closestDistance) {\n closestDistance = distance;\n closestPage = pageNumber;\n }\n });\n\n if (closestPage !== currentPage) {\n goToPage(closestPage);\n }\n }, [currentPage, goToPage, isScrollMode, totalPages]);\n\n // ==================== 缩放控制 ====================\n const zoom = useCallback(\n (delta: number) => {\n const newScale = Math.max(minScale, Math.min(maxScale, scale + delta));\n if (controlledScale === undefined) {\n setInternalScale(newScale);\n }\n onScaleChange?.(newScale);\n },\n [scale, minScale, maxScale, controlledScale, onScaleChange]\n );\n\n // ==================== 旋转控制 ====================\n const rotate = useCallback(() => {\n const newRotation = (rotation + 90) % 360;\n if (controlledRotation === undefined) {\n setInternalRotation(newRotation);\n }\n onRotationChange?.(newRotation);\n }, [rotation, controlledRotation, onRotationChange]);\n\n // ==================== 处理窗口大小变化 ====================\n const debouncedUpdatePageWidth = useDebounce((width: number) => {\n setPageWidth(width);\n }, 100);\n\n // Use ResizeObserver to track container size changes\n useEffect(() => {\n if (!pdfContainerRef.current) return;\n\n const container = pdfContainerRef.current;\n const updateWidth = () => {\n debouncedUpdatePageWidth(container.clientWidth);\n };\n\n // Initial measurement\n updateWidth();\n\n // Set up ResizeObserver\n const resizeObserver = new ResizeObserver(() => {\n updateWidth();\n });\n\n resizeObserver.observe(container);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [debouncedUpdatePageWidth]);\n\n // ==================== 键盘快捷键 ====================\n useEffect(() => {\n if (!enableHotkeys) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement | null;\n const activeElement =\n typeof document !== 'undefined'\n ? (document.activeElement as HTMLElement | null)\n : null;\n const focusedElement = target || activeElement;\n const role = focusedElement?.getAttribute('role');\n\n if (\n focusedElement &&\n (focusedElement.tagName === 'INPUT' ||\n focusedElement.tagName === 'TEXTAREA' ||\n focusedElement.tagName === 'SELECT' ||\n focusedElement.isContentEditable ||\n role === 'textbox' ||\n role === 'spinbutton')\n ) {\n return;\n }\n\n // Ctrl/Cmd + 加号: 放大\n if ((e.ctrlKey || e.metaKey) && (e.key === '=' || e.key === '+')) {\n e.preventDefault();\n zoom(0.1);\n }\n // Ctrl/Cmd + 减号: 缩小\n else if ((e.ctrlKey || e.metaKey) && e.key === '-') {\n e.preventDefault();\n zoom(-0.1);\n }\n // 左箭头: 上一页\n else if (!isScrollMode && e.key === 'ArrowLeft') {\n e.preventDefault();\n goToPage(currentPage - 1);\n }\n // 右箭头: 下一页\n else if (!isScrollMode && e.key === 'ArrowRight') {\n e.preventDefault();\n goToPage(currentPage + 1);\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [enableHotkeys, currentPage, goToPage, isScrollMode, zoom]);\n\n // ==================== 全屏切换 ====================\n const toggleFullscreen = useCallback(async () => {\n if (typeof document === 'undefined') return;\n\n if (!document.fullscreenElement) {\n try {\n await readerRef.current?.requestFullscreen?.();\n setIsFullscreen(true);\n } catch (err) {\n console.error('Error attempting to enable fullscreen:', err);\n }\n } else {\n if (document.exitFullscreen) {\n await document.exitFullscreen();\n setIsFullscreen(false);\n }\n }\n }, []);\n\n // ==================== 监听全屏状态变化 ====================\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement);\n };\n\n document.addEventListener('fullscreenchange', handleFullscreenChange);\n return () => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange);\n };\n }, []);\n\n // ==================== 处理侧边栏页面点击 ====================\n const handleSidebarPageClick = useCallback(\n (pageNumber: number) => {\n goToPage(pageNumber);\n setShowAllPages(false);\n },\n [goToPage]\n );\n\n // ==================== 渲染工具栏 ====================\n const renderToolbar = () => {\n if (!showToolbar) return null;\n\n return (\n <div\n className={`flex items-center justify-between gap-4 border-b px-4 py-2 ${toolbarClassName || ''}`}\n >\n <div className=\"flex items-center gap-2\">\n {/* 侧边栏切换 */}\n {showSidebar && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowSidebarState(!showSidebarState)}\n title={showSidebarState ? '隐藏侧边栏' : '显示侧边栏'}\n >\n <PanelLeftIcon />\n </Button>\n )}\n\n {/* 缩放控制 */}\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => zoom(-0.1)}\n disabled={scale <= minScale}\n >\n <ZoomOutIcon />\n </Button>\n <span className=\"min-w-[3rem] text-center text-sm\">\n {Math.round(scale * 100)}%\n </span>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => zoom(0.1)}\n disabled={scale >= maxScale}\n >\n <ZoomInIcon />\n </Button>\n\n {/* 旋转控制 */}\n {showRotation && (\n <Button variant=\"outline\" size=\"icon\" onClick={rotate}>\n <RotateCwIcon />\n </Button>\n )}\n\n {/* 显示模式切换 */}\n {showModeToggle && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowAllPages(!showAllPages)}\n title={showAllPages ? '单页模式' : '滚动模式'}\n >\n {showAllPages ? <ScrollTextIcon /> : <FileTextIcon />}\n </Button>\n )}\n\n {/* 全屏切换 */}\n {showFullscreen && (\n <Button variant=\"outline\" size=\"icon\" onClick={toggleFullscreen}>\n {isFullscreen ? <Minimize2Icon /> : <Maximize2Icon />}\n </Button>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {!isScrollMode && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage <= 1}\n >\n <ChevronLeftIcon />\n </Button>\n )}\n\n <Input\n type=\"number\"\n min={1}\n max={totalPages}\n value={currentPage}\n onChange={(e) => goToPage(parseInt(e.target.value) || 1)}\n disabled={isScrollMode}\n readOnly={isScrollMode}\n title={isScrollMode ? '滚动模式下页码仅显示当前位置' : undefined}\n className=\"w-16 text-center\"\n />\n <span className=\"text-sm text-muted-foreground\">/ {totalPages}</span>\n\n {!isScrollMode && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={totalPages > 0 && currentPage >= totalPages}\n >\n <ChevronRightIcon />\n </Button>\n )}\n </div>\n </div>\n );\n };\n\n // ==================== 渲染加载状态 ====================\n const renderLoading = () => (\n <div className=\"flex h-full items-center justify-center\">\n <p className=\"text-muted-foreground\">{loadingText}</p>\n </div>\n );\n\n // ==================== 渲染错误状态 ====================\n const renderError = () => (\n <div className=\"flex h-full min-h-[400px] items-center justify-center px-4 text-center text-destructive\">\n <div className=\"max-w-md\">\n <p className=\"mb-2 text-lg font-medium\">文件加载失败</p>\n <p className=\"text-sm opacity-80\">{error?.message}</p>\n </div>\n </div>\n );\n\n // ==================== 渲染 PDF 文档 ====================\n const renderPDFDocument = () => {\n if (!ReactPDF) return renderLoading();\n\n const { Document, Page } = ReactPDF;\n\n return (\n <div\n ref={pdfContainerRef}\n onScroll={isScrollMode ? syncScrollModeCurrentPage : undefined}\n className={`pdf-container flex-1 overflow-y-auto ${contentClassName || ''}`}\n >\n <div className=\"flex min-h-full justify-center px-4\">\n <Document\n key={url}\n file={url}\n onLoadError={onDocumentLoadError}\n options={pdfOptions}\n loading={renderLoading()}\n error={renderError()}\n onLoadSuccess={onDocumentLoadSuccess}\n >\n {error ? (\n renderError()\n ) : showAllPages ? (\n // 显示所有页面模式\n Array.from(new Array(totalPages), (_el, index) => (\n <div\n key={`page_${index + 1}`}\n ref={(element) => setPageRef(index + 1, element)}\n data-page-number={index + 1}\n className={`mb-4 ${pageClassName || ''}`}\n >\n <Page\n pageNumber={index + 1}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n width={pageWidth}\n scale={scale}\n rotate={rotation}\n onRenderSuccess={() => onPageRender?.(index + 1)}\n />\n </div>\n ))\n ) : (\n // 单页模式\n <div className={pageClassName || ''}>\n <Page\n pageNumber={currentPage}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n width={pageWidth}\n scale={scale}\n rotate={rotation}\n onRenderSuccess={() => onPageRender?.(currentPage)}\n />\n </div>\n )}\n </Document>\n </div>\n </div>\n );\n };\n\n // ==================== 渲染侧边栏 ====================\n const renderSidebar = () => {\n if (!showSidebar || !showSidebarState || !pdfDocument) return null;\n\n // 使用导入的 PDFSidebar 组件\n const PDFSidebarComponent = PDFSidebar;\n\n return (\n <PDFSidebarComponent\n pdfDocument={pdfDocument}\n currentPage={currentPage}\n onPageClick={handleSidebarPageClick}\n components={{\n Tabs: components.Tabs!,\n TabsList: components.TabsList!,\n TabsTrigger: components.TabsTrigger!,\n TabsContent: components.TabsContent!,\n ScrollArea: components.ScrollArea!,\n Skeleton,\n }}\n />\n );\n };\n\n // ==================== 渲染移动端导航 ====================\n const renderMobileNav = () => {\n if (!enableMobileNav || isScrollMode) return null;\n\n return (\n <div className=\"fixed bottom-4 left-1/2 z-50 flex -translate-x-1/2 gap-2 md:hidden\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={isScrollMode || currentPage <= 1}\n title={isScrollMode ? '滚动模式下通过滚动定位页面' : undefined}\n >\n <ChevronLeftIcon />\n <span className=\"ml-1\">上一页</span>\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={isScrollMode || currentPage >= totalPages}\n title={isScrollMode ? '滚动模式下通过滚动定位页面' : undefined}\n >\n <span className=\"mr-1\">下一页</span>\n <ChevronRightIcon />\n </Button>\n </div>\n );\n };\n\n // ==================== 组件验证 ====================\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n // 验证侧边栏所需的所有组件\n if (showSidebar) {\n const missingComponents: string[] = [];\n if (!components.Tabs) missingComponents.push('Tabs');\n if (!components.TabsList) missingComponents.push('TabsList');\n if (!components.TabsTrigger) missingComponents.push('TabsTrigger');\n if (!components.TabsContent) missingComponents.push('TabsContent');\n if (!components.ScrollArea) missingComponents.push('ScrollArea');\n\n if (missingComponents.length > 0) {\n const missingComponentsText =\n missingComponents.length === 1\n ? missingComponents[0]\n : `${missingComponents.slice(0, -1).join('、')} 和 ${missingComponents[missingComponents.length - 1]}`;\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:侧边栏功能需要注入 {missingComponentsText} 组件\n </div>\n );\n }\n }\n\n return (\n <div ref={readerRef}>\n <Card className={className}>\n {renderToolbar()}\n <CardContent\n className=\"p-0\"\n style={{ height: isFullscreen ? '100vh' : contentHeight }}\n >\n <div className=\"flex h-full flex-col\">\n {/* PDF 显示区域 */}\n <div className=\"flex flex-1 overflow-hidden\">\n {renderSidebar()}\n {isLoading\n ? renderLoading()\n : error\n ? renderError()\n : renderPDFDocument()}\n </div>\n </div>\n </CardContent>\n </Card>\n {renderMobileNav()}\n </div>\n );\n}\n"],"names":["useDebounce","callback","delay","timeoutRef","useRef","useCallback","args","PDFReader","url","initialPage","initialScale","initialRotation","controlledPage","onPageChange","controlledScale","onScaleChange","controlledRotation","onRotationChange","minScale","maxScale","showToolbar","showSidebar","showRotation","showModeToggle","showFullscreen","enableHotkeys","enableMobileNav","initialDisplayMode","className","toolbarClassName","contentClassName","contentHeight","pageClassName","workerUrl","cMapUrl","standardFontDataUrl","components","onLoadSuccess","onLoadError","onPageRender","loadingText","errorText","pdfDocument","setPdfDocument","useState","internalPage","setInternalPage","internalScale","setInternalScale","internalRotation","setInternalRotation","isLoading","setIsLoading","error","setError","totalPages","setTotalPages","isFullscreen","setIsFullscreen","showAllPages","setShowAllPages","showSidebarState","setShowSidebarState","useEffect","pageWidth","setPageWidth","ReactPDF","setReactPDF","readerRef","pdfContainerRef","pageRefs","currentPage","scale","rotation","isPageControlled","isScrollMode","Card","CardContent","Button","Input","Skeleton","pdfOptions","useMemo","options","isMounted","pdfModule","pdfjs","workerVersion","err","loadError","onDocumentLoadError","onDocumentLoadSuccess","pdf","page","goToPage","newPage","setPageRef","pageNumber","element","syncScrollModeCurrentPage","container","containerTop","closestPage","closestDistance","distance","zoom","delta","newScale","rotate","newRotation","debouncedUpdatePageWidth","width","updateWidth","resizeObserver","handleKeyDown","e","target","activeElement","focusedElement","role","toggleFullscreen","_b","_a","handleFullscreenChange","handleSidebarPageClick","renderToolbar","jsxs","jsx","PanelLeftIcon","ZoomOutIcon","ZoomInIcon","RotateCwIcon","ScrollTextIcon","FileTextIcon","Minimize2Icon","Maximize2Icon","ChevronLeftIcon","ChevronRightIcon","renderLoading","renderError","renderPDFDocument","Document","Page","_el","index","renderSidebar","PDFSidebarComponent","PDFSidebar","renderMobileNav","missingComponents","missingComponentsText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pdf-reader.cjs","sources":["../src/components/PDFReader.tsx"],"sourcesContent":["import {\n ChevronLeft as ChevronLeftIcon,\n ChevronRight as ChevronRightIcon,\n FileText as FileTextIcon,\n Maximize2 as Maximize2Icon,\n Minimize2 as Minimize2Icon,\n PanelLeft as PanelLeftIcon,\n RotateCw as RotateCwIcon,\n ScrollText as ScrollTextIcon,\n ZoomIn as ZoomInIcon,\n ZoomOut as ZoomOutIcon,\n} from 'lucide-react';\nimport { useState, useCallback, useEffect, useMemo, useRef } from 'react';\nimport type { HTMLAttributes } from 'react';\n\nimport type {\n CardComponent,\n ButtonComponent,\n InputComponent,\n SkeletonComponent,\n} from '../types/component-types';\n\nimport type { PDFDocumentProxy } from './PDFSidebar';\nimport { PDFSidebar } from './PDFSidebar';\n\n/**\n * PDFReader UI 组件接口\n */\nexport interface PDFReaderUIComponents {\n /** Card 组件 (必需) */\n Card: CardComponent;\n /** CardContent 组件 (必需) */\n CardContent: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n /** Button 组件 (必需) */\n Button: ButtonComponent;\n /** Input 组件 (必需) */\n Input: InputComponent;\n /** Skeleton 组件 (必需) */\n Skeleton: SkeletonComponent;\n /** Tabs 组件 (showSidebar=true 时必需) */\n Tabs?: React.ComponentType<{\n value?: string;\n onValueChange?: (value: string) => void;\n children?: React.ReactNode;\n defaultValue?: string;\n }>;\n /** TabsList 组件 (showSidebar=true 时必需) */\n TabsList?: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n /** TabsTrigger 组件 (showSidebar=true 时必需) */\n TabsTrigger?: React.ComponentType<{\n value: string;\n children?: React.ReactNode;\n }>;\n /** TabsContent 组件 (showSidebar=true 时必需) */\n TabsContent?: React.ComponentType<{\n value: string;\n children?: React.ReactNode;\n }>;\n /** ScrollArea 组件 (showSidebar=true 时必需) */\n ScrollArea?: React.ComponentType<HTMLAttributes<HTMLDivElement>>;\n}\n\n/**\n * PDFReader 组件 Props\n */\nexport interface PDFReaderProps {\n // ==================== 基础配置 ====================\n /** PDF 文件 URL (必需) */\n url: string;\n\n // ==================== 初始状态 ====================\n /** 初始页码 (默认 1) */\n initialPage?: number;\n /** 初始缩放比例 (默认 1.0) */\n initialScale?: number;\n /** 初始旋转角度 (默认 0) */\n initialRotation?: number;\n\n // ==================== 受控模式 ====================\n /** 当前页码 (受控) */\n currentPage?: number;\n /** 页码变化回调 */\n onPageChange?: (page: number) => void;\n /** 缩放比例 (受控) */\n scale?: number;\n /** 缩放变化回调 */\n onScaleChange?: (scale: number) => void;\n /** 旋转角度 (受控) */\n rotation?: number;\n /** 旋转变化回调 */\n onRotationChange?: (rotation: number) => void;\n\n // ==================== 缩放限制 ====================\n /** 最小缩放比例 (默认 0.5) */\n minScale?: number;\n /** 最大缩放比例 (默认 2.5) */\n maxScale?: number;\n\n // ==================== 功能开关 ====================\n /** 显示工具栏 (默认 true) */\n showToolbar?: boolean;\n /** 显示侧边栏 (默认 true) */\n showSidebar?: boolean;\n /** 显示旋转按钮 (默认 true) */\n showRotation?: boolean;\n /** 显示模式切换按钮 (默认 true) */\n showModeToggle?: boolean;\n /** 显示全屏按钮 (默认 true) */\n showFullscreen?: boolean;\n /** 启用键盘快捷键 (默认 true) */\n enableHotkeys?: boolean;\n /** 启用移动端导航 (默认 true) */\n enableMobileNav?: boolean;\n\n // ==================== 显示模式 ====================\n /** 显示模式: 'scroll' 显示所有页面, 'single' 单页模式 (默认 'single') */\n displayMode?: 'scroll' | 'single';\n\n // ==================== 样式定制 ====================\n /** 容器类名 */\n className?: string;\n /** 工具栏类名 */\n toolbarClassName?: string;\n /** 内容区域类名 */\n contentClassName?: string;\n /** 阅读区域高度限制 (默认 '80vh') */\n contentHeight?: string | number;\n /** 页面类名 */\n pageClassName?: string;\n\n // ==================== Worker 配置 ====================\n /** Worker 文件 URL (可选,默认使用 CDN) */\n workerUrl?: string;\n /** CMap 文件 URL (可选,默认使用 CDN) */\n cMapUrl?: string;\n /** 标准字体数据 URL (可选,默认使用 CDN) */\n standardFontDataUrl?: string;\n\n // ==================== UI 组件注入 ====================\n /** UI 组件 */\n components: PDFReaderUIComponents;\n\n // ==================== 回调函数 ====================\n /** 加载成功回调 */\n onLoadSuccess?: (pdf: PDFDocumentProxy) => void;\n /** 加载错误回调 */\n onLoadError?: (error: Error) => void;\n /** 页面渲染回调 */\n onPageRender?: (pageIndex: number) => void;\n\n // ==================== 文本配置 ====================\n /** 加载文本 (默认 '正在加载PDF文档...') */\n loadingText?: string;\n /** 错误文本 (默认 'PDF加载失败') */\n errorText?: string;\n}\n\n/**\n * debounce hook (替代 lodash.debounce)\n */\nfunction useDebounce<T extends (...args: any[]) => any>(\n callback: T,\n delay: number\n): T {\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(\n undefined\n );\n return useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => callback(...args), delay);\n },\n [callback, delay]\n ) as T;\n}\n\n/**\n * PDFReader 组件\n *\n * 功能完整的 PDF 阅读器组件,支持侧边栏导航、页面旋转、显示模式切换等高级特性。\n *\n * @example\n * ```tsx\n * import { PDFReader } from '@turinhub/atomix-common-ui/pdf-reader';\n * import { Card, Button, Input, Label, Skeleton } from '@/components/ui';\n * import { Tabs, ScrollArea } from '@/components/ui';\n *\n * <PDFReader\n * url=\"/documents/sample.pdf\"\n * components={{\n * Card,\n * CardContent: Card.Content,\n * Button,\n * Input,\n * Label,\n * Skeleton,\n * Tabs,\n * TabsList: Tabs.List,\n * TabsTrigger: Tabs.Trigger,\n * TabsContent: Tabs.Content,\n * ScrollArea,\n * }}\n * initialPage={1}\n * initialScale={1.0}\n * showSidebar={true}\n * showRotation={true}\n * showModeToggle={true}\n * enableHotkeys={true}\n * />\n * ```\n */\nexport function PDFReader({\n url,\n initialPage = 1,\n initialScale = 1.0,\n initialRotation = 0,\n currentPage: controlledPage,\n onPageChange,\n scale: controlledScale,\n onScaleChange,\n rotation: controlledRotation,\n onRotationChange,\n minScale = 0.5,\n maxScale = 2.5,\n showToolbar = true,\n showSidebar = true,\n showRotation = true,\n showModeToggle = true,\n showFullscreen = true,\n enableHotkeys = true,\n enableMobileNav = true,\n displayMode: initialDisplayMode = 'single',\n className,\n toolbarClassName,\n contentClassName,\n contentHeight = '80vh',\n pageClassName,\n workerUrl,\n cMapUrl,\n standardFontDataUrl,\n components,\n onLoadSuccess,\n onLoadError,\n onPageRender,\n loadingText = '正在加载PDF文档...',\n errorText = 'PDF加载失败',\n}: PDFReaderProps) {\n // ==================== 状态管理 ====================\n const [pdfDocument, setPdfDocument] = useState<PDFDocumentProxy | null>(null);\n const [internalPage, setInternalPage] = useState(initialPage);\n const [internalScale, setInternalScale] = useState(initialScale);\n const [internalRotation, setInternalRotation] = useState(initialRotation);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [totalPages, setTotalPages] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [showAllPages, setShowAllPages] = useState(\n initialDisplayMode === 'scroll'\n );\n const [showSidebarState, setShowSidebarState] = useState(showSidebar);\n\n // Sync showSidebarState with prop changes\n useEffect(() => {\n setShowSidebarState(showSidebar);\n }, [showSidebar]);\n\n const [pageWidth, setPageWidth] = useState<number | undefined>(undefined);\n\n // 动态导入 react-pdf\n const [ReactPDF, setReactPDF] = useState<any>(null);\n\n const readerRef = useRef<HTMLDivElement>(null);\n const pdfContainerRef = useRef<HTMLDivElement>(null);\n const pageRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n // 使用受控或非受控模式\n const currentPage = controlledPage ?? internalPage;\n const scale = controlledScale ?? internalScale;\n const rotation = controlledRotation ?? internalRotation;\n const isPageControlled = controlledPage !== undefined;\n const isScrollMode = showAllPages;\n\n // ==================== 组件解构 ====================\n const { Card, CardContent, Button, Input, Skeleton } = components || {};\n\n useEffect(() => {\n setPdfDocument(null);\n setTotalPages(0);\n setError(null);\n setIsLoading(false);\n if (!isPageControlled) {\n setInternalPage(Math.max(1, initialPage));\n }\n }, [url, initialPage, isPageControlled]);\n\n // ==================== PDF 选项 ====================\n const pdfOptions = useMemo(() => {\n const options: Record<string, unknown> = {\n withCredentials: false,\n };\n\n if (cMapUrl) {\n options.cMapUrl = cMapUrl;\n options.cMapPacked = true;\n }\n\n if (standardFontDataUrl) {\n options.standardFontDataUrl = standardFontDataUrl;\n }\n\n return options;\n }, [cMapUrl, standardFontDataUrl]);\n\n // ==================== 动态导入 react-pdf ====================\n useEffect(() => {\n let isMounted = true;\n\n const loadReactPDF = async () => {\n try {\n // 动态导入 react-pdf\n const pdfModule = await import('react-pdf');\n\n // 设置 worker\n if (typeof window !== 'undefined') {\n const pdfjs = (pdfModule as any).pdfjs;\n const workerVersion = pdfjs?.version;\n\n if (pdfjs?.GlobalWorkerOptions && workerVersion) {\n if (workerUrl) {\n pdfjs.GlobalWorkerOptions.workerSrc = workerUrl;\n } else {\n // 使用 CDN\n pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${workerVersion}/build/pdf.worker.min.mjs`;\n }\n\n // 如果没有提供自定义 URL,使用 CDN 默认值\n if (!cMapUrl && pdfjs.GlobalWorkerOptions) {\n (pdfjs.GlobalWorkerOptions as any).cMapUrl =\n `https://unpkg.com/pdfjs-dist@${workerVersion}/cmaps/`;\n }\n if (!standardFontDataUrl && pdfjs.GlobalWorkerOptions) {\n (pdfjs.GlobalWorkerOptions as any).standardFontDataUrl =\n `https://unpkg.com/pdfjs-dist@${workerVersion}/standard_fonts/`;\n }\n }\n }\n\n if (isMounted) {\n setReactPDF(pdfModule);\n }\n } catch (err) {\n if (isMounted) {\n const loadError =\n err instanceof Error ? err : new Error('无法加载 react-pdf 库');\n setError(loadError);\n setIsLoading(false);\n onLoadError?.(loadError);\n }\n }\n };\n\n loadReactPDF();\n\n return () => {\n isMounted = false;\n };\n }, [workerUrl, cMapUrl, standardFontDataUrl, onLoadError]);\n\n // ==================== 处理加载错误 ====================\n const onDocumentLoadError = useCallback(\n (err: Error) => {\n console.error('PDF加载失败:', err);\n console.error('PDF URL:', url);\n setPdfDocument(null);\n setTotalPages(0);\n setError(\n new Error(`${errorText}: ${err.message || '请检查文件路径或网络连接'}`)\n );\n setIsLoading(false);\n onLoadError?.(err);\n },\n [url, errorText, onLoadError]\n );\n\n const onDocumentLoadSuccess = useCallback(\n (pdf: PDFDocumentProxy) => {\n setPdfDocument(pdf);\n setTotalPages(pdf.numPages);\n setError(null);\n setIsLoading(false);\n\n if (!isPageControlled) {\n setInternalPage((page) =>\n Math.max(1, Math.min(page, Math.max(pdf.numPages, 1)))\n );\n }\n\n onLoadSuccess?.(pdf);\n },\n [isPageControlled, onLoadSuccess]\n );\n\n // ==================== 页面导航 ====================\n const goToPage = useCallback(\n (page: number) => {\n if (!Number.isFinite(page)) return;\n const newPage =\n totalPages > 0\n ? Math.max(1, Math.min(Math.trunc(page), totalPages))\n : Math.max(1, Math.trunc(page));\n if (!isPageControlled) {\n setInternalPage(newPage);\n }\n if (newPage !== currentPage) {\n onPageChange?.(newPage);\n }\n },\n [totalPages, isPageControlled, currentPage, onPageChange]\n );\n\n const setPageRef = useCallback(\n (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 );\n\n const syncScrollModeCurrentPage = useCallback(() => {\n const container = pdfContainerRef.current;\n if (!container || !isScrollMode || totalPages <= 0) return;\n\n const containerTop = container.getBoundingClientRect().top;\n let closestPage = currentPage;\n let closestDistance = Number.POSITIVE_INFINITY;\n\n pageRefs.current.forEach((element, pageNumber) => {\n const distance = Math.abs(\n element.getBoundingClientRect().top - containerTop\n );\n if (distance < closestDistance) {\n closestDistance = distance;\n closestPage = pageNumber;\n }\n });\n\n if (closestPage !== currentPage) {\n goToPage(closestPage);\n }\n }, [currentPage, goToPage, isScrollMode, totalPages]);\n\n // ==================== 缩放控制 ====================\n const zoom = useCallback(\n (delta: number) => {\n const newScale = Math.max(minScale, Math.min(maxScale, scale + delta));\n if (controlledScale === undefined) {\n setInternalScale(newScale);\n }\n onScaleChange?.(newScale);\n },\n [scale, minScale, maxScale, controlledScale, onScaleChange]\n );\n\n // ==================== 旋转控制 ====================\n const rotate = useCallback(() => {\n const newRotation = (rotation + 90) % 360;\n if (controlledRotation === undefined) {\n setInternalRotation(newRotation);\n }\n onRotationChange?.(newRotation);\n }, [rotation, controlledRotation, onRotationChange]);\n\n // ==================== 处理窗口大小变化 ====================\n const debouncedUpdatePageWidth = useDebounce((width: number) => {\n setPageWidth(width);\n }, 100);\n\n // Use ResizeObserver to track container size changes\n useEffect(() => {\n if (!pdfContainerRef.current) return;\n\n const container = pdfContainerRef.current;\n const updateWidth = () => {\n debouncedUpdatePageWidth(container.clientWidth);\n };\n\n // Initial measurement\n updateWidth();\n\n // Set up ResizeObserver\n const resizeObserver = new ResizeObserver(() => {\n updateWidth();\n });\n\n resizeObserver.observe(container);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [debouncedUpdatePageWidth]);\n\n // ==================== 键盘快捷键 ====================\n useEffect(() => {\n if (!enableHotkeys) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement | null;\n const activeElement =\n typeof document !== 'undefined'\n ? (document.activeElement as HTMLElement | null)\n : null;\n const focusedElement = target || activeElement;\n const role = focusedElement?.getAttribute('role');\n\n if (\n focusedElement &&\n (focusedElement.tagName === 'INPUT' ||\n focusedElement.tagName === 'TEXTAREA' ||\n focusedElement.tagName === 'SELECT' ||\n focusedElement.isContentEditable ||\n role === 'textbox' ||\n role === 'spinbutton')\n ) {\n return;\n }\n\n // Ctrl/Cmd + 加号: 放大\n if ((e.ctrlKey || e.metaKey) && (e.key === '=' || e.key === '+')) {\n e.preventDefault();\n zoom(0.1);\n }\n // Ctrl/Cmd + 减号: 缩小\n else if ((e.ctrlKey || e.metaKey) && e.key === '-') {\n e.preventDefault();\n zoom(-0.1);\n }\n // 左箭头: 上一页\n else if (!isScrollMode && e.key === 'ArrowLeft') {\n e.preventDefault();\n goToPage(currentPage - 1);\n }\n // 右箭头: 下一页\n else if (!isScrollMode && e.key === 'ArrowRight') {\n e.preventDefault();\n goToPage(currentPage + 1);\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [enableHotkeys, currentPage, goToPage, isScrollMode, zoom]);\n\n // ==================== 全屏切换 ====================\n const toggleFullscreen = useCallback(async () => {\n if (typeof document === 'undefined') return;\n\n if (!document.fullscreenElement) {\n try {\n await readerRef.current?.requestFullscreen?.();\n setIsFullscreen(true);\n } catch (err) {\n console.error('Error attempting to enable fullscreen:', err);\n }\n } else {\n if (document.exitFullscreen) {\n await document.exitFullscreen();\n setIsFullscreen(false);\n }\n }\n }, []);\n\n // ==================== 监听全屏状态变化 ====================\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement);\n };\n\n document.addEventListener('fullscreenchange', handleFullscreenChange);\n return () => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange);\n };\n }, []);\n\n // ==================== 处理侧边栏页面点击 ====================\n const handleSidebarPageClick = useCallback(\n (pageNumber: number) => {\n goToPage(pageNumber);\n setShowAllPages(false);\n },\n [goToPage]\n );\n\n // ==================== 渲染工具栏 ====================\n const renderToolbar = () => {\n if (!showToolbar) return null;\n\n return (\n <div\n className={`flex items-center justify-between gap-4 border-b px-4 py-2 ${toolbarClassName || ''}`}\n >\n <div className=\"flex items-center gap-2\">\n {/* 侧边栏切换 */}\n {showSidebar && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowSidebarState(!showSidebarState)}\n aria-label={showSidebarState ? '隐藏侧边栏' : '显示侧边栏'}\n title={showSidebarState ? '隐藏侧边栏' : '显示侧边栏'}\n >\n <PanelLeftIcon />\n </Button>\n )}\n\n {/* 缩放控制 */}\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => zoom(-0.1)}\n disabled={scale <= minScale}\n aria-label=\"缩小\"\n title=\"缩小\"\n >\n <ZoomOutIcon />\n </Button>\n <span className=\"min-w-[3rem] text-center text-sm\">\n {Math.round(scale * 100)}%\n </span>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => zoom(0.1)}\n disabled={scale >= maxScale}\n aria-label=\"放大\"\n title=\"放大\"\n >\n <ZoomInIcon />\n </Button>\n\n {/* 旋转控制 */}\n {showRotation && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={rotate}\n aria-label=\"顺时针旋转\"\n title=\"顺时针旋转\"\n >\n <RotateCwIcon />\n </Button>\n )}\n\n {/* 显示模式切换 */}\n {showModeToggle && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowAllPages(!showAllPages)}\n aria-label={showAllPages ? '切换到单页模式' : '切换到滚动模式'}\n title={showAllPages ? '单页模式' : '滚动模式'}\n >\n {showAllPages ? <ScrollTextIcon /> : <FileTextIcon />}\n </Button>\n )}\n\n {/* 全屏切换 */}\n {showFullscreen && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={toggleFullscreen}\n aria-label={isFullscreen ? '退出全屏' : '进入全屏'}\n title={isFullscreen ? '退出全屏' : '进入全屏'}\n >\n {isFullscreen ? <Minimize2Icon /> : <Maximize2Icon />}\n </Button>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {!isScrollMode && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage <= 1}\n aria-label=\"上一页\"\n title=\"上一页\"\n >\n <ChevronLeftIcon />\n </Button>\n )}\n\n <Input\n type=\"number\"\n name=\"pdf-page\"\n min={1}\n max={totalPages}\n value={currentPage}\n onChange={(e) => goToPage(parseInt(e.target.value) || 1)}\n disabled={isScrollMode}\n readOnly={isScrollMode}\n aria-label=\"当前页码\"\n inputMode=\"numeric\"\n autoComplete=\"off\"\n title={isScrollMode ? '滚动模式下页码仅显示当前位置' : undefined}\n className=\"w-16 text-center\"\n />\n <span className=\"text-sm text-muted-foreground\">/ {totalPages}</span>\n\n {!isScrollMode && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={totalPages > 0 && currentPage >= totalPages}\n aria-label=\"下一页\"\n title=\"下一页\"\n >\n <ChevronRightIcon />\n </Button>\n )}\n </div>\n </div>\n );\n };\n\n // ==================== 渲染加载状态 ====================\n const renderLoading = () => (\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <p className=\"text-muted-foreground\">{loadingText}</p>\n </div>\n );\n\n // ==================== 渲染错误状态 ====================\n const renderError = () => (\n <div\n className=\"flex h-full min-h-[400px] items-center justify-center px-4 text-center text-destructive\"\n role=\"alert\"\n >\n <div className=\"max-w-md\">\n <p className=\"mb-2 text-lg font-medium\">文件加载失败</p>\n <p className=\"text-sm opacity-80\">{error?.message}</p>\n </div>\n </div>\n );\n\n // ==================== 渲染 PDF 文档 ====================\n const renderPDFDocument = () => {\n if (!ReactPDF) return renderLoading();\n\n const { Document, Page } = ReactPDF;\n\n return (\n <div\n ref={pdfContainerRef}\n onScroll={isScrollMode ? syncScrollModeCurrentPage : undefined}\n className={`pdf-container flex-1 overflow-y-auto ${contentClassName || ''}`}\n >\n <div className=\"flex min-h-full justify-center px-4\">\n <Document\n key={url}\n file={url}\n onLoadError={onDocumentLoadError}\n options={pdfOptions}\n loading={renderLoading()}\n error={renderError()}\n onLoadSuccess={onDocumentLoadSuccess}\n >\n {error ? (\n renderError()\n ) : showAllPages ? (\n // 显示所有页面模式\n Array.from(new Array(totalPages), (_el, index) => (\n <div\n key={`page_${index + 1}`}\n ref={(element) => setPageRef(index + 1, element)}\n data-page-number={index + 1}\n className={`mb-4 ${pageClassName || ''}`}\n >\n <Page\n pageNumber={index + 1}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n width={pageWidth}\n scale={scale}\n rotate={rotation}\n onRenderSuccess={() => onPageRender?.(index + 1)}\n />\n </div>\n ))\n ) : (\n // 单页模式\n <div className={pageClassName || ''}>\n <Page\n pageNumber={currentPage}\n renderTextLayer={false}\n renderAnnotationLayer={false}\n width={pageWidth}\n scale={scale}\n rotate={rotation}\n onRenderSuccess={() => onPageRender?.(currentPage)}\n />\n </div>\n )}\n </Document>\n </div>\n </div>\n );\n };\n\n // ==================== 渲染侧边栏 ====================\n const renderSidebar = () => {\n if (!showSidebar || !showSidebarState || !pdfDocument) return null;\n\n // 使用导入的 PDFSidebar 组件\n const PDFSidebarComponent = PDFSidebar;\n\n return (\n <PDFSidebarComponent\n pdfDocument={pdfDocument}\n currentPage={currentPage}\n onPageClick={handleSidebarPageClick}\n components={{\n Tabs: components.Tabs!,\n TabsList: components.TabsList!,\n TabsTrigger: components.TabsTrigger!,\n TabsContent: components.TabsContent!,\n ScrollArea: components.ScrollArea!,\n Skeleton,\n }}\n />\n );\n };\n\n // ==================== 渲染移动端导航 ====================\n const renderMobileNav = () => {\n if (!enableMobileNav || isScrollMode) return null;\n\n return (\n <div className=\"fixed bottom-4 left-1/2 z-50 flex -translate-x-1/2 gap-2 md:hidden\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={isScrollMode || currentPage <= 1}\n title={isScrollMode ? '滚动模式下通过滚动定位页面' : undefined}\n >\n <ChevronLeftIcon />\n <span className=\"ml-1\">上一页</span>\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={isScrollMode || currentPage >= totalPages}\n title={isScrollMode ? '滚动模式下通过滚动定位页面' : undefined}\n >\n <span className=\"mr-1\">下一页</span>\n <ChevronRightIcon />\n </Button>\n </div>\n );\n };\n\n // ==================== 组件验证 ====================\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n // 验证侧边栏所需的所有组件\n if (showSidebar) {\n const missingComponents: string[] = [];\n if (!components.Tabs) missingComponents.push('Tabs');\n if (!components.TabsList) missingComponents.push('TabsList');\n if (!components.TabsTrigger) missingComponents.push('TabsTrigger');\n if (!components.TabsContent) missingComponents.push('TabsContent');\n if (!components.ScrollArea) missingComponents.push('ScrollArea');\n\n if (missingComponents.length > 0) {\n const missingComponentsText =\n missingComponents.length === 1\n ? missingComponents[0]\n : `${missingComponents.slice(0, -1).join('、')} 和 ${missingComponents[missingComponents.length - 1]}`;\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:侧边栏功能需要注入 {missingComponentsText} 组件\n </div>\n );\n }\n }\n\n return (\n <div ref={readerRef}>\n <Card className={className}>\n {renderToolbar()}\n <CardContent\n className=\"p-0\"\n style={{ height: isFullscreen ? '100vh' : contentHeight }}\n >\n <div className=\"flex h-full flex-col\">\n {/* PDF 显示区域 */}\n <div className=\"flex flex-1 overflow-hidden\">\n {renderSidebar()}\n {isLoading\n ? renderLoading()\n : error\n ? renderError()\n : renderPDFDocument()}\n </div>\n </div>\n </CardContent>\n </Card>\n {renderMobileNav()}\n </div>\n );\n}\n"],"names":["useDebounce","callback","delay","timeoutRef","useRef","useCallback","args","PDFReader","url","initialPage","initialScale","initialRotation","controlledPage","onPageChange","controlledScale","onScaleChange","controlledRotation","onRotationChange","minScale","maxScale","showToolbar","showSidebar","showRotation","showModeToggle","showFullscreen","enableHotkeys","enableMobileNav","initialDisplayMode","className","toolbarClassName","contentClassName","contentHeight","pageClassName","workerUrl","cMapUrl","standardFontDataUrl","components","onLoadSuccess","onLoadError","onPageRender","loadingText","errorText","pdfDocument","setPdfDocument","useState","internalPage","setInternalPage","internalScale","setInternalScale","internalRotation","setInternalRotation","isLoading","setIsLoading","error","setError","totalPages","setTotalPages","isFullscreen","setIsFullscreen","showAllPages","setShowAllPages","showSidebarState","setShowSidebarState","useEffect","pageWidth","setPageWidth","ReactPDF","setReactPDF","readerRef","pdfContainerRef","pageRefs","currentPage","scale","rotation","isPageControlled","isScrollMode","Card","CardContent","Button","Input","Skeleton","pdfOptions","useMemo","options","isMounted","pdfModule","pdfjs","workerVersion","err","loadError","onDocumentLoadError","onDocumentLoadSuccess","pdf","page","goToPage","newPage","setPageRef","pageNumber","element","syncScrollModeCurrentPage","container","containerTop","closestPage","closestDistance","distance","zoom","delta","newScale","rotate","newRotation","debouncedUpdatePageWidth","width","updateWidth","resizeObserver","handleKeyDown","e","target","activeElement","focusedElement","role","toggleFullscreen","_b","_a","handleFullscreenChange","handleSidebarPageClick","renderToolbar","jsxs","jsx","PanelLeftIcon","ZoomOutIcon","ZoomInIcon","RotateCwIcon","ScrollTextIcon","FileTextIcon","Minimize2Icon","Maximize2Icon","ChevronLeftIcon","ChevronRightIcon","renderLoading","renderError","renderPDFDocument","Document","Page","_el","index","renderSidebar","PDFSidebarComponent","PDFSidebar","renderMobileNav","missingComponents","missingComponentsText"],"mappings":"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"}
|