{"version":3,"file":"index-BbpSFL9t.mjs","sources":["../../src/renderers/Image/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport { motion } from 'framer-motion';\nimport { Loader2, ZoomIn, ZoomOut, RotateCw, RotateCcw, Scan, RefreshCw } from 'lucide-react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport {\n  decodeInWorker,\n  detectImageFormat,\n  getLoaderForMimeType,\n  shouldUseWorker,\n} from '@eternalheart/file-preview-core';\nimport type { PreviewFile } from '@eternalheart/file-preview-core';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\nimport type { ToolbarGroup } from '../toolbar.types';\n\nconst OriginalSizeIcon: React.FC<{ className?: string }> = ({ className }) => (\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth=\"2\"\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n    className={className}\n  >\n    <text x=\"12\" y=\"17.5\" textAnchor=\"middle\" fontSize=\"20\" fontWeight=\"bold\" fill=\"currentColor\" stroke=\"none\">\n      1:1\n    </text>\n  </svg>\n);\n\nexport interface ImageRendererHandle extends RendererHandle {\n  fitToWidth: () => void;\n  resetView: () => void;\n}\n\ninterface ImageRendererProps {\n  url: string;\n  fileSize?: number;\n  file?: PreviewFile | File;\n}\n\nexport const ImageRenderer = forwardRef<ImageRendererHandle, ImageRendererProps>(({\n  url,\n  fileSize,\n  file,\n}, ref) => {\n  const t = useTranslator();\n\n  // 内部状态管理\n  const [loaded, setLoaded] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n  const [decoding, setDecoding] = useState(false);\n  const [decodeProgress, setDecodeProgress] = useState(0);\n  const [decodeError, setDecodeError] = useState<string | null>(null);\n  const [imageSrc, setImageSrc] = useState<string>('');\n  const [currentPage, setCurrentPage] = useState(1);\n  const [totalPages, setTotalPages] = useState(1);\n  const [position, setPosition] = useState({ x: 0, y: 0 });\n  const [isDragging, setIsDragging] = useState(false);\n  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n  const [zoom, setZoom] = useState(1);\n  const [rotation, setRotation] = useState(0);\n  const [naturalSize, setNaturalSize] = useState({ width: 0, height: 0 });\n\n  const imgRef = useRef<HTMLImageElement>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n  const blobUrlRef = useRef<string | null>(null);\n  const fileBlobRef = useRef<Blob | null>(null);\n  const loaderRef = useRef<any>(null);\n  const pageCacheRef = useRef<Map<number, string>>(new Map());\n  const isTouchDevice = useRef(false);\n  const touchStartDistance = useRef(0);\n  const touchStartZoom = useRef(1);\n  const touchStartPos = useRef({ x: 0, y: 0 });\n  const lastTapTime = useRef(0);\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  }, [rotation, notifyToolbarChange]);\n\n  // 解码逻辑：检测格式并按需解码\n  useEffect(() => {\n    let cancelled = false;\n\n    const decodeIfNeeded = async () => {\n      // 重置状态：清空 src 以避免上一张图片的 onLoad/onError 误触发到新文件\n      setImageSrc('');\n      setLoaded(false);\n      setError(null);\n      setDecoding(false);\n      setDecodeError(null);\n      setDecodeProgress(0);\n      setPosition({ x: 0, y: 0 });\n      setZoom(1);\n      setRotation(0);\n      setCurrentPage(1);\n      setTotalPages(1);\n\n      // 清理旧的 blob URL 与缓存\n      if (blobUrlRef.current) {\n        URL.revokeObjectURL(blobUrlRef.current);\n        blobUrlRef.current = null;\n      }\n      pageCacheRef.current.forEach((url) => URL.revokeObjectURL(url));\n      pageCacheRef.current.clear();\n      fileBlobRef.current = null;\n      loaderRef.current = null;\n\n      // 如果没有 file 对象，直接使用 url\n      if (!file) {\n        if (!cancelled) setImageSrc(url);\n        return;\n      }\n\n      try {\n        // 检测图片格式\n        const mimeType = await detectImageFormat(file);\n        const loader = await getLoaderForMimeType(mimeType);\n\n        // 如果不需要解码，直接使用原 URL\n        if (!loader || !(await loader.needsDecode(mimeType))) {\n          if (!cancelled) setImageSrc(url);\n          return;\n        }\n\n        // 需要解码\n        setDecoding(true);\n\n        // 获取文件 Blob\n        let fileBlob: Blob;\n        if (file instanceof Blob) {\n          fileBlob = file;\n        } else {\n          const response = await fetch(url);\n          if (!response.ok) throw new Error('Failed to fetch file');\n          fileBlob = await response.blob();\n        }\n\n        if (cancelled) return;\n\n        // 缓存 Blob 与 loader 以便后续翻页\n        fileBlobRef.current = fileBlob;\n        loaderRef.current = loader;\n\n        // 获取元数据（用于检测多页 TIFF）\n        if (loader.getMetadata) {\n          try {\n            const metadata = await loader.getMetadata(fileBlob);\n            if (!cancelled && metadata.pageCount && metadata.pageCount > 1) {\n              setTotalPages(metadata.pageCount);\n            }\n          } catch {\n            // 忽略元数据获取失败\n          }\n        }\n\n        const decodeOptions = {\n          page: 1,\n          fullQuality: false,\n          onProgress: (percent: number) => {\n            if (!cancelled) {\n              setDecodeProgress(percent);\n            }\n          },\n        };\n\n        // HEIC/RAW/PSD 等耗时格式优先在 Worker 中解码。\n        // Worker 消息不能传递回调函数，因此只传递可结构化克隆的选项；\n        // CSP、旧浏览器或第三方库不兼容 Worker 时回退主线程。\n        let decodedBlob;\n        if (shouldUseWorker(mimeType)) {\n          try {\n            decodedBlob = await decodeInWorker(\n              mimeType,\n              await fileBlob.arrayBuffer(),\n              { page: 1, fullQuality: false },\n            );\n          } catch {\n            decodedBlob = await loader.decode(fileBlob, decodeOptions);\n          }\n        } else {\n          decodedBlob = await loader.decode(fileBlob, decodeOptions);\n        }\n\n        if (cancelled) return;\n\n        // 生成 blob URL\n        const blobUrl = typeof decodedBlob === 'string'\n          ? decodedBlob\n          : URL.createObjectURL(decodedBlob);\n\n        blobUrlRef.current = blobUrl;\n        pageCacheRef.current.set(1, blobUrl);\n        setImageSrc(blobUrl);\n        setDecoding(false);\n      } catch (err: any) {\n        if (!cancelled) {\n          setDecodeError(err?.message || '解码失败');\n          setDecoding(false);\n        }\n      }\n    };\n\n    decodeIfNeeded();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [url, file]);\n\n  // 多页 TIFF 翻页：切换页码时重新解码\n  const handlePageChange = useCallback(async (page: number) => {\n    if (!fileBlobRef.current || !loaderRef.current) return;\n    if (page < 1 || page > totalPages) return;\n\n    // 命中缓存：直接切换\n    const cached = pageCacheRef.current.get(page);\n    if (cached) {\n      setCurrentPage(page);\n      setImageSrc(cached);\n      return;\n    }\n\n    // 解码新页面\n    setDecoding(true);\n    try {\n      const decodedBlob = await loaderRef.current.decode(fileBlobRef.current, { page });\n      const blobUrl = typeof decodedBlob === 'string'\n        ? decodedBlob\n        : URL.createObjectURL(decodedBlob);\n\n      // LRU：缓存超过 10 页时删除最早的\n      if (pageCacheRef.current.size >= 10) {\n        const firstKey = pageCacheRef.current.keys().next().value;\n        if (firstKey !== undefined) {\n          const oldUrl = pageCacheRef.current.get(firstKey);\n          if (oldUrl) URL.revokeObjectURL(oldUrl);\n          pageCacheRef.current.delete(firstKey);\n        }\n      }\n\n      pageCacheRef.current.set(page, blobUrl);\n      setCurrentPage(page);\n      setImageSrc(blobUrl);\n      setDecoding(false);\n    } catch (err: any) {\n      setDecodeError(err?.message || '翻页解码失败');\n      setDecoding(false);\n    }\n  }, [totalPages]);\n\n  // Cleanup blob URL on unmount\n  useEffect(() => {\n    return () => {\n      if (blobUrlRef.current) {\n        URL.revokeObjectURL(blobUrlRef.current);\n      }\n      pageCacheRef.current.forEach((url) => URL.revokeObjectURL(url));\n      pageCacheRef.current.clear();\n    };\n  }, []);\n\n  const handleLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {\n    setLoaded(true);\n    const img = e.currentTarget;\n    const newNaturalSize = { width: img.naturalWidth, height: img.naturalHeight };\n    setNaturalSize(newNaturalSize);\n\n    // 图片加载完成后，自动适应窗口大小\n    if (containerRef.current && newNaturalSize.width > 0 && newNaturalSize.height > 0) {\n      const containerWidth = containerRef.current.clientWidth;\n      const containerHeight = containerRef.current.clientHeight;\n      const scaleX = containerWidth / newNaturalSize.width;\n      const scaleY = containerHeight / newNaturalSize.height;\n      const newZoom = Math.min(scaleX, scaleY);\n      setZoom(Math.max(0.01, Math.min(10, newZoom)));\n      setPosition({ x: 0, y: 0 });\n    }\n  };\n\n  // 边界限制：确保图片至少有一部分可见\n  const clampPosition = useCallback((pos: { x: number; y: number }, currentZoom: number) => {\n    const container = containerRef.current;\n    if (!container || naturalSize.width === 0) return pos;\n\n    const containerW = container.clientWidth;\n    const containerH = container.clientHeight;\n    const imgW = naturalSize.width * currentZoom;\n    const imgH = naturalSize.height * currentZoom;\n\n    // 至少保留 margin px 的图片在视口内\n    const margin = Math.min(80, containerW * 0.15, containerH * 0.15);\n    const rangeX = (containerW + imgW) / 2 - margin;\n    const rangeY = (containerH + imgH) / 2 - margin;\n\n    return {\n      x: rangeX > 0 ? Math.max(-rangeX, Math.min(rangeX, pos.x)) : 0,\n      y: rangeY > 0 ? Math.max(-rangeY, Math.min(rangeY, pos.y)) : 0,\n    };\n  }, [naturalSize]);\n\n  const handleError = () => {\n    setError(t('image.load_failed'));\n    setLoaded(true);\n  };\n\n  // 双击复原：居中 + 缩放100%\n  const handleDoubleClick = () => {\n    setPosition({ x: 0, y: 0 });\n    setZoom(1);\n  };\n\n  // 触屏事件处理\n  const handleTouchStart = useCallback((e: TouchEvent) => {\n    isTouchDevice.current = true;\n    e.preventDefault();\n\n    const touches = e.touches;\n    if (touches.length === 1) {\n      // 单指拖拽\n      setIsDragging(true);\n      setDragStart({\n        x: touches[0].clientX - position.x,\n        y: touches[0].clientY - position.y,\n      });\n\n      // 双击检测\n      const now = Date.now();\n      if (now - lastTapTime.current < 300) {\n        // 双击复原：居中 + 缩放100%\n        setPosition({ x: 0, y: 0 });\n        setZoom(1);\n      }\n      lastTapTime.current = now;\n    } else if (touches.length === 2) {\n      // 双指缩放初始化\n      setIsDragging(false);\n      const distance = Math.hypot(\n        touches[1].clientX - touches[0].clientX,\n        touches[1].clientY - touches[0].clientY\n      );\n      touchStartDistance.current = distance;\n      touchStartZoom.current = zoom;\n      touchStartPos.current = { ...position };\n    }\n  }, [position, zoom]);\n\n  const handleTouchMove = useCallback((e: TouchEvent) => {\n    e.preventDefault();\n\n    const touches = e.touches;\n    if (touches.length === 1 && isDragging) {\n      // 单指拖拽\n      setPosition(clampPosition({\n        x: touches[0].clientX - dragStart.x,\n        y: touches[0].clientY - dragStart.y,\n      }, zoom));\n    } else if (touches.length === 2) {\n      // 双指缩放\n      const container = containerRef.current;\n      if (!container) return;\n\n      const distance = Math.hypot(\n        touches[1].clientX - touches[0].clientX,\n        touches[1].clientY - touches[0].clientY\n      );\n\n      // 最小距离变化阈值，防止抖动\n      if (Math.abs(distance - touchStartDistance.current) < 5) return;\n\n      const scale = distance / touchStartDistance.current;\n      const newZoom = Math.max(0.01, Math.min(10, touchStartZoom.current * scale));\n\n      // 双指中心点作为缩放原点\n      const rect = container.getBoundingClientRect();\n      const centerX = (touches[0].clientX + touches[1].clientX) / 2 - rect.left - rect.width / 2;\n      const centerY = (touches[0].clientY + touches[1].clientY) / 2 - rect.top - rect.height / 2;\n\n      const zoomScale = newZoom / zoom;\n      setPosition(clampPosition({\n        x: centerX - zoomScale * (centerX - touchStartPos.current.x),\n        y: centerY - zoomScale * (centerY - touchStartPos.current.y),\n      }, newZoom));\n\n      setZoom(newZoom);\n    }\n  }, [isDragging, dragStart, zoom, clampPosition]);\n\n  const handleTouchEnd = useCallback(() => {\n    setIsDragging(false);\n    touchStartDistance.current = 0;\n  }, []);\n\n  // 鼠标滚轮缩放 —— 以鼠标位置为缩放原点\n  // 使用原生事件 + passive: false,确保 preventDefault 生效,\n  // 避免滚轮事件冒泡触发外层(如嵌入模式下的页面滚动)\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    const handleWheelNative = (e: WheelEvent) => {\n      e.preventDefault();\n      e.stopPropagation();\n\n      const rect = container.getBoundingClientRect();\n      const mouseX = e.clientX - rect.left - rect.width / 2;\n      const mouseY = e.clientY - rect.top - rect.height / 2;\n\n      const delta = e.deltaY > 0 ? -0.05 : 0.05;\n\n      setZoom(prev => {\n        const newZoom = Math.max(0.01, Math.min(10, prev + delta));\n        const scale = newZoom / prev;\n\n        setPosition(pos => clampPosition({\n          x: mouseX - scale * (mouseX - pos.x),\n          y: mouseY - scale * (mouseY - pos.y),\n        }, newZoom));\n\n        return newZoom;\n      });\n    };\n\n    container.addEventListener('wheel', handleWheelNative, { passive: false });\n    return () => container.removeEventListener('wheel', handleWheelNative);\n  }, [clampPosition]);\n\n  // 触屏事件监听器\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    container.addEventListener('touchstart', handleTouchStart, { passive: false });\n    container.addEventListener('touchmove', handleTouchMove, { passive: false });\n    container.addEventListener('touchend', handleTouchEnd);\n    container.addEventListener('touchcancel', handleTouchEnd);\n\n    return () => {\n      container.removeEventListener('touchstart', handleTouchStart);\n      container.removeEventListener('touchmove', handleTouchMove);\n      container.removeEventListener('touchend', handleTouchEnd);\n      container.removeEventListener('touchcancel', handleTouchEnd);\n    };\n  }, [handleTouchStart, handleTouchMove, handleTouchEnd]);\n\n  const handleMouseDown = useCallback((e: React.MouseEvent) => {\n    if (isTouchDevice.current) return;\n    if (e.button !== 0) return;\n    setIsDragging(true);\n    setDragStart({\n      x: e.clientX - position.x,\n      y: e.clientY - position.y,\n    });\n  }, [position]);\n\n  const handleMouseMove = useCallback((e: React.MouseEvent) => {\n    if (isTouchDevice.current) return;\n    if (!isDragging) return;\n    setPosition(clampPosition({\n      x: e.clientX - dragStart.x,\n      y: e.clientY - dragStart.y,\n    }, zoom));\n  }, [isDragging, dragStart, zoom, clampPosition]);\n\n  const handleMouseUp = useCallback(() => {\n    if (isTouchDevice.current) return;\n    setIsDragging(false);\n  }, []);\n\n  // 工具栏事件处理\n  const handleZoomIn = useCallback(() => {\n    setZoom(z => Math.min(z + 0.1, 10));\n  }, []);\n\n  const handleZoomOut = useCallback(() => {\n    setZoom(z => Math.max(z - 0.1, 0.01));\n  }, []);\n\n  const handleRotateLeft = useCallback(() => {\n    setRotation(r => r - 90);\n  }, []);\n\n  const handleRotateRight = useCallback(() => {\n    setRotation(r => r + 90);\n  }, []);\n\n  const handleFitToWidth = useCallback(() => {\n    if (containerRef.current && naturalSize.width > 0 && naturalSize.height > 0) {\n      const containerWidth = containerRef.current.clientWidth;\n      const containerHeight = containerRef.current.clientHeight;\n      const scaleX = containerWidth / naturalSize.width;\n      const scaleY = containerHeight / naturalSize.height;\n      const newZoom = Math.min(scaleX, scaleY);\n      setZoom(Math.max(0.01, Math.min(10, newZoom)));\n      setRotation(0);\n      setPosition({ x: 0, y: 0 });\n    }\n  }, [naturalSize]);\n\n  const handleOriginalSize = useCallback(() => {\n    setZoom(1);\n    setRotation(0);\n    setPosition({ x: 0, y: 0 });\n  }, []);\n\n  const handleReset = useCallback(() => {\n    // 重置为自适应窗口，而不是原始尺寸\n    handleFitToWidth();\n  }, [handleFitToWidth]);\n\n  // 工具栏配置\n  const getToolbarGroups = useCallback((): ToolbarGroup[] => [\n    {\n      items: [\n        { type: 'button', icon: <ZoomOut className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.zoom_out'), action: handleZoomOut, disabled: zoom <= 0.01 },\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 >= 10 },\n      ],\n    },\n    {\n      items: [\n        { type: 'button', icon: <Scan className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.fit_to_window'), action: handleFitToWidth },\n        { type: 'button', icon: <OriginalSizeIcon className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.original_size'), action: handleOriginalSize },\n      ],\n    },\n    {\n      items: [\n        { type: 'button', icon: <RotateCcw className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.rotate_left'), action: handleRotateLeft },\n        { type: 'button', icon: <RotateCw className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.rotate_right'), action: handleRotateRight },\n      ],\n    },\n    {\n      items: [\n        { type: 'button', icon: <RefreshCw className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.reset'), action: handleReset },\n      ],\n    },\n  ], [zoom, t, handleZoomIn, handleZoomOut, handleFitToWidth, handleOriginalSize, handleRotateLeft, handleRotateRight, 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    fitToWidth: handleFitToWidth,\n    resetView: handleReset,\n  }), [getToolbarGroups, handleFitToWidth, handleReset]);\n\n  return (\n    <div\n      ref={containerRef}\n      className=\"rfp-relative rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-overflow-hidden\"\n      onMouseDown={handleMouseDown}\n      onMouseMove={handleMouseMove}\n      onMouseUp={handleMouseUp}\n      onMouseLeave={handleMouseUp}\n      style={{ cursor: isDragging ? 'grabbing' : 'grab', touchAction: 'none' }}\n    >\n      {/* 解码中 */}\n      {decoding && (\n        <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-flex-col rfp-items-center rfp-justify-center rfp-bg-surface-1/80 rfp-z-10\">\n          <Loader2 className=\"rfp-w-12 rfp-h-12 rfp-text-fg-primary rfp-animate-spin\" />\n          <p className=\"rfp-mt-4 rfp-text-fg-secondary\">\n            正在解码... {decodeProgress > 0 && `${Math.round(decodeProgress)}%`}\n          </p>\n        </div>\n      )}\n\n      {/* 解码错误 */}\n      {decodeError && (\n        <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-1/80 rfp-z-10\">\n          <RendererError message={t('image.decode_failed')} detail={decodeError} />\n        </div>\n      )}\n\n      {!loaded && !error && !decoding && !decodeError && (\n        <div className=\"rfp-flex rfp-items-center rfp-justify-center\">\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        <RendererError message={error} />\n      )}\n\n      {imageSrc && (\n        <motion.img\n          ref={imgRef}\n          src={imageSrc}\n          alt=\"Preview\"\n          className={`rfp-max-w-none rfp-select-none ${!loaded || error || decodeError ? 'rfp-hidden' : ''}`}\n          style={{\n            transform: `translate(${position.x}px, ${position.y}px) scale(${zoom}) rotate(${rotation}deg)`,\n            transformOrigin: 'center',\n            transition: isDragging ? 'none' : 'transform 0.3s ease-out',\n          }}\n          onLoad={handleLoad}\n          onError={handleError}\n          onDoubleClick={handleDoubleClick}\n          initial={{ opacity: 0 }}\n          animate={{ opacity: loaded && !error && !decodeError ? 1 : 0 }}\n          transition={{ duration: 0.3 }}\n          draggable={false}\n        />\n      )}\n\n      {/* 右下角分辨率 */}\n      {loaded && !error && naturalSize.width > 0 && (\n        <div className=\"rfp-absolute rfp-bottom-2 rfp-right-3 rfp-text-[10px] rfp-text-fg-disabled hover:rfp-text-fg-secondary rfp-transition-colors rfp-pointer-events-auto rfp-select-none rfp-cursor-default\">\n          {naturalSize.width} × {naturalSize.height}{fileSize != null && ` · ${fileSize < 1024 ? `${fileSize} B` : fileSize < 1024 * 1024 ? `${(fileSize / 1024).toFixed(1)} KB` : `${(fileSize / (1024 * 1024)).toFixed(1)} MB`}`}\n        </div>\n      )}\n\n      {/* 多页 TIFF 翻页器 */}\n      {totalPages > 1 && (\n        <div className=\"rfp-absolute rfp-bottom-2 rfp-left-1/2 -rfp-translate-x-1/2 rfp-flex rfp-items-center rfp-gap-2 rfp-px-3 rfp-py-1.5 rfp-bg-surface-toolbar rfp-border rfp-border-line rfp-rounded-lg rfp-text-sm rfp-text-fg-primary rfp-shadow-md\">\n          <button\n            type=\"button\"\n            onClick={() => handlePageChange(currentPage - 1)}\n            disabled={currentPage <= 1 || decoding}\n            className=\"rfp-px-2 rfp-py-0.5 rfp-rounded hover:rfp-bg-surface-nav-hover disabled:rfp-opacity-40 disabled:rfp-cursor-not-allowed\"\n          >\n            上一页\n          </button>\n          <span className=\"rfp-text-fg-secondary rfp-tabular-nums\">\n            {currentPage} / {totalPages}\n          </span>\n          <button\n            type=\"button\"\n            onClick={() => handlePageChange(currentPage + 1)}\n            disabled={currentPage >= totalPages || decoding}\n            className=\"rfp-px-2 rfp-py-0.5 rfp-rounded hover:rfp-bg-surface-nav-hover disabled:rfp-opacity-40 disabled:rfp-cursor-not-allowed\"\n          >\n            下一页\n          </button>\n        </div>\n      )}\n    </div>\n  );\n});\n"],"names":["OriginalSizeIcon","className","jsx","ImageRenderer","forwardRef","url","fileSize","file","ref","t","useTranslator","loaded","setLoaded","useState","error","setError","decoding","setDecoding","decodeProgress","setDecodeProgress","decodeError","setDecodeError","imageSrc","setImageSrc","currentPage","setCurrentPage","totalPages","setTotalPages","position","setPosition","isDragging","setIsDragging","dragStart","setDragStart","zoom","setZoom","rotation","setRotation","naturalSize","setNaturalSize","imgRef","useRef","containerRef","blobUrlRef","fileBlobRef","loaderRef","pageCacheRef","isTouchDevice","touchStartDistance","touchStartZoom","touchStartPos","lastTapTime","listenersRef","notifyToolbarChange","useCallback","listener","useEffect","cancelled","mimeType","detectImageFormat","loader","getLoaderForMimeType","fileBlob","response","metadata","decodeOptions","percent","decodedBlob","shouldUseWorker","decodeInWorker","blobUrl","err","handlePageChange","page","cached","firstKey","oldUrl","handleLoad","e","img","newNaturalSize","containerWidth","containerHeight","scaleX","scaleY","newZoom","clampPosition","pos","currentZoom","container","containerW","containerH","imgW","imgH","margin","rangeX","rangeY","handleError","handleDoubleClick","handleTouchStart","touches","now","distance","handleTouchMove","scale","rect","centerX","centerY","zoomScale","handleTouchEnd","handleWheelNative","mouseX","mouseY","delta","prev","handleMouseDown","handleMouseMove","handleMouseUp","handleZoomIn","z","handleZoomOut","handleRotateLeft","r","handleRotateRight","handleFitToWidth","handleOriginalSize","handleReset","getToolbarGroups","ZoomOut","ZoomIn","Scan","RotateCcw","RotateCw","RefreshCw","useImperativeHandle","jsxs","Loader2","RendererError","motion"],"mappings":"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"}