@turinhub/atomix-common-ui 0.4.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.
Files changed (104) hide show
  1. package/README.md +20 -2
  2. package/dist/AuthPanel-CTKx618F.cjs +2 -0
  3. package/dist/AuthPanel-CTKx618F.cjs.map +1 -0
  4. package/dist/AuthPanel-Cn_WwmjX.js +703 -0
  5. package/dist/AuthPanel-Cn_WwmjX.js.map +1 -0
  6. package/dist/PDFSidebar-4DtXqqzN.cjs +2 -0
  7. package/dist/PDFSidebar-4DtXqqzN.cjs.map +1 -0
  8. package/dist/PDFSidebar-ClnrF4Br.js +239 -0
  9. package/dist/PDFSidebar-ClnrF4Br.js.map +1 -0
  10. package/dist/auth.cjs +2 -0
  11. package/dist/auth.cjs.map +1 -0
  12. package/dist/auth.d.ts +11 -0
  13. package/dist/auth.d.ts.map +1 -0
  14. package/dist/auth.js +9 -0
  15. package/dist/auth.js.map +1 -0
  16. package/dist/components/AuthLoginPanel.d.ts +55 -0
  17. package/dist/components/AuthLoginPanel.d.ts.map +1 -0
  18. package/dist/components/AuthPageShell.d.ts +11 -0
  19. package/dist/components/AuthPageShell.d.ts.map +1 -0
  20. package/dist/components/AuthPanel.d.ts +20 -0
  21. package/dist/components/AuthPanel.d.ts.map +1 -0
  22. package/dist/components/AuthRegisterPanel.d.ts +34 -0
  23. package/dist/components/AuthRegisterPanel.d.ts.map +1 -0
  24. package/dist/components/AuthVisualCarousel.d.ts +22 -0
  25. package/dist/components/AuthVisualCarousel.d.ts.map +1 -0
  26. package/dist/components/DataTable.d.ts +2 -2
  27. package/dist/components/DataTable.d.ts.map +1 -1
  28. package/dist/components/ImageReader.d.ts +44 -0
  29. package/dist/components/ImageReader.d.ts.map +1 -0
  30. package/dist/components/MarkdownReader.d.ts.map +1 -1
  31. package/dist/components/PDFReader.d.ts.map +1 -1
  32. package/dist/components/PDFSidebar.d.ts.map +1 -1
  33. package/dist/components/SimplePDFReader.d.ts.map +1 -1
  34. package/dist/components/TableHeader.d.ts.map +1 -1
  35. package/dist/components/TablePagination.d.ts +2 -1
  36. package/dist/components/TablePagination.d.ts.map +1 -1
  37. package/dist/components/VideoReader.d.ts +39 -0
  38. package/dist/components/VideoReader.d.ts.map +1 -0
  39. package/dist/components/media-utils.d.ts +9 -0
  40. package/dist/components/media-utils.d.ts.map +1 -0
  41. package/dist/components/ui/switch.d.ts +5 -0
  42. package/dist/components/ui/switch.d.ts.map +1 -0
  43. package/dist/data-table.cjs +1 -1
  44. package/dist/data-table.cjs.map +1 -1
  45. package/dist/data-table.js +83 -73
  46. package/dist/data-table.js.map +1 -1
  47. package/dist/file-upload.cjs +1 -1
  48. package/dist/file-upload.cjs.map +1 -1
  49. package/dist/file-upload.js +36 -36
  50. package/dist/file-upload.js.map +1 -1
  51. package/dist/image-reader.cjs +2 -0
  52. package/dist/image-reader.cjs.map +1 -0
  53. package/dist/image-reader.d.ts +3 -0
  54. package/dist/image-reader.d.ts.map +1 -0
  55. package/dist/image-reader.js +215 -0
  56. package/dist/image-reader.js.map +1 -0
  57. package/dist/index.cjs +1 -1
  58. package/dist/index.d.ts +10 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +8 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/markdown-reader.cjs +1 -1
  63. package/dist/markdown-reader.cjs.map +1 -1
  64. package/dist/markdown-reader.js +28 -24
  65. package/dist/markdown-reader.js.map +1 -1
  66. package/dist/media-utils-5UPuocc1.js +23 -0
  67. package/dist/media-utils-5UPuocc1.js.map +1 -0
  68. package/dist/media-utils-X1dDYP9W.cjs +2 -0
  69. package/dist/media-utils-X1dDYP9W.cjs.map +1 -0
  70. package/dist/pdf-reader.cjs +1 -1
  71. package/dist/pdf-reader.cjs.map +1 -1
  72. package/dist/pdf-reader.js +170 -121
  73. package/dist/pdf-reader.js.map +1 -1
  74. package/dist/pdf-sidebar.cjs +1 -1
  75. package/dist/pdf-sidebar.js +1 -1
  76. package/dist/simple-pdf-reader.cjs +1 -1
  77. package/dist/simple-pdf-reader.cjs.map +1 -1
  78. package/dist/simple-pdf-reader.js +138 -105
  79. package/dist/simple-pdf-reader.js.map +1 -1
  80. package/dist/table-header.cjs +1 -1
  81. package/dist/table-header.cjs.map +1 -1
  82. package/dist/table-header.js +42 -34
  83. package/dist/table-header.js.map +1 -1
  84. package/dist/table-pagination.cjs +1 -1
  85. package/dist/table-pagination.cjs.map +1 -1
  86. package/dist/table-pagination.js +49 -43
  87. package/dist/table-pagination.js.map +1 -1
  88. package/dist/types/component-types.d.ts +2 -0
  89. package/dist/types/component-types.d.ts.map +1 -1
  90. package/dist/video-reader.cjs +2 -0
  91. package/dist/video-reader.cjs.map +1 -0
  92. package/dist/video-reader.d.ts +3 -0
  93. package/dist/video-reader.d.ts.map +1 -0
  94. package/dist/video-reader.js +158 -0
  95. package/dist/video-reader.js.map +1 -0
  96. package/package.json +32 -1
  97. package/dist/PDFSidebar-BBtucLK6.js +0 -232
  98. package/dist/PDFSidebar-BBtucLK6.js.map +0 -1
  99. package/dist/PDFSidebar-Di0D-yPS.cjs +0 -2
  100. package/dist/PDFSidebar-Di0D-yPS.cjs.map +0 -1
  101. package/dist/index-BiA_tnaq.cjs +0 -13
  102. package/dist/index-BiA_tnaq.cjs.map +0 -1
  103. package/dist/index-BypbGNpR.js +0 -18821
  104. package/dist/index-BypbGNpR.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ const a = (s, e) => {
2
+ const t = e || s;
3
+ if (!t) return "";
4
+ const n = t.split(/[?#]/)[0] || "", o = n.split(".").pop();
5
+ return !o || o === n ? "" : o.toLowerCase();
6
+ }, c = ({
7
+ src: s,
8
+ fileName: e,
9
+ mimeType: t,
10
+ supportedExtensions: n,
11
+ supportedMimeTypes: o
12
+ }) => {
13
+ const i = t == null ? void 0 : t.toLowerCase();
14
+ if (i && o.some((r) => i === r))
15
+ return !0;
16
+ const u = a(s, e);
17
+ return u ? n.some((r) => r === u) : !t;
18
+ };
19
+ export {
20
+ a as g,
21
+ c as i
22
+ };
23
+ //# sourceMappingURL=media-utils-5UPuocc1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-utils-5UPuocc1.js","sources":["../src/components/media-utils.ts"],"sourcesContent":["export const getMediaExtension = (src?: string, fileName?: string) => {\n const candidate = fileName || src;\n if (!candidate) return '';\n\n const withoutQuery = candidate.split(/[?#]/)[0] || '';\n const extension = withoutQuery.split('.').pop();\n\n if (!extension || extension === withoutQuery) return '';\n\n return extension.toLowerCase();\n};\n\nexport const isSupportedMediaSource = ({\n src,\n fileName,\n mimeType,\n supportedExtensions,\n supportedMimeTypes,\n}: {\n src?: string;\n fileName?: string;\n mimeType?: string;\n supportedExtensions: readonly string[];\n supportedMimeTypes: readonly string[];\n}) => {\n const normalizedMimeType = mimeType?.toLowerCase();\n\n if (\n normalizedMimeType &&\n supportedMimeTypes.some((type) => normalizedMimeType === type)\n ) {\n return true;\n }\n\n const extension = getMediaExtension(src, fileName);\n\n return extension\n ? supportedExtensions.some((supported) => supported === extension)\n : !mimeType;\n};\n"],"names":["getMediaExtension","src","fileName","candidate","withoutQuery","extension","isSupportedMediaSource","mimeType","supportedExtensions","supportedMimeTypes","normalizedMimeType","type","supported"],"mappings":"AAAO,MAAMA,IAAoB,CAACC,GAAcC,MAAsB;AACpE,QAAMC,IAAYD,KAAYD;AAC9B,MAAI,CAACE,EAAW,QAAO;AAEvB,QAAMC,IAAeD,EAAU,MAAM,MAAM,EAAE,CAAC,KAAK,IAC7CE,IAAYD,EAAa,MAAM,GAAG,EAAE,IAAA;AAE1C,SAAI,CAACC,KAAaA,MAAcD,IAAqB,KAE9CC,EAAU,YAAA;AACnB,GAEaC,IAAyB,CAAC;AAAA,EACrC,KAAAL;AAAA,EACA,UAAAC;AAAA,EACA,UAAAK;AAAA,EACA,qBAAAC;AAAA,EACA,oBAAAC;AACF,MAMM;AACJ,QAAMC,IAAqBH,KAAA,gBAAAA,EAAU;AAErC,MACEG,KACAD,EAAmB,KAAK,CAACE,MAASD,MAAuBC,CAAI;AAE7D,WAAO;AAGT,QAAMN,IAAYL,EAAkBC,GAAKC,CAAQ;AAEjD,SAAOG,IACHG,EAAoB,KAAK,CAACI,MAAcA,MAAcP,CAAS,IAC/D,CAACE;AACP;"}
@@ -0,0 +1,2 @@
1
+ "use strict";const c=(n,s)=>{const t=s||n;if(!t)return"";const o=t.split(/[?#]/)[0]||"",e=o.split(".").pop();return!e||e===o?"":e.toLowerCase()},a=({src:n,fileName:s,mimeType:t,supportedExtensions:o,supportedMimeTypes:e})=>{const i=t==null?void 0:t.toLowerCase();if(i&&e.some(r=>i===r))return!0;const u=c(n,s);return u?o.some(r=>r===u):!t};exports.getMediaExtension=c;exports.isSupportedMediaSource=a;
2
+ //# sourceMappingURL=media-utils-X1dDYP9W.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-utils-X1dDYP9W.cjs","sources":["../src/components/media-utils.ts"],"sourcesContent":["export const getMediaExtension = (src?: string, fileName?: string) => {\n const candidate = fileName || src;\n if (!candidate) return '';\n\n const withoutQuery = candidate.split(/[?#]/)[0] || '';\n const extension = withoutQuery.split('.').pop();\n\n if (!extension || extension === withoutQuery) return '';\n\n return extension.toLowerCase();\n};\n\nexport const isSupportedMediaSource = ({\n src,\n fileName,\n mimeType,\n supportedExtensions,\n supportedMimeTypes,\n}: {\n src?: string;\n fileName?: string;\n mimeType?: string;\n supportedExtensions: readonly string[];\n supportedMimeTypes: readonly string[];\n}) => {\n const normalizedMimeType = mimeType?.toLowerCase();\n\n if (\n normalizedMimeType &&\n supportedMimeTypes.some((type) => normalizedMimeType === type)\n ) {\n return true;\n }\n\n const extension = getMediaExtension(src, fileName);\n\n return extension\n ? supportedExtensions.some((supported) => supported === extension)\n : !mimeType;\n};\n"],"names":["getMediaExtension","src","fileName","candidate","withoutQuery","extension","isSupportedMediaSource","mimeType","supportedExtensions","supportedMimeTypes","normalizedMimeType","type","supported"],"mappings":"aAAO,MAAMA,EAAoB,CAACC,EAAcC,IAAsB,CACpE,MAAMC,EAAYD,GAAYD,EAC9B,GAAI,CAACE,EAAW,MAAO,GAEvB,MAAMC,EAAeD,EAAU,MAAM,MAAM,EAAE,CAAC,GAAK,GAC7CE,EAAYD,EAAa,MAAM,GAAG,EAAE,IAAA,EAE1C,MAAI,CAACC,GAAaA,IAAcD,EAAqB,GAE9CC,EAAU,YAAA,CACnB,EAEaC,EAAyB,CAAC,CACrC,IAAAL,EACA,SAAAC,EACA,SAAAK,EACA,oBAAAC,EACA,mBAAAC,CACF,IAMM,CACJ,MAAMC,EAAqBH,GAAA,YAAAA,EAAU,cAErC,GACEG,GACAD,EAAmB,KAAME,GAASD,IAAuBC,CAAI,EAE7D,MAAO,GAGT,MAAMN,EAAYL,EAAkBC,EAAKC,CAAQ,EAEjD,OAAOG,EACHG,EAAoB,KAAMI,GAAcA,IAAcP,CAAS,EAC/D,CAACE,CACP"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./jsx-runtime-BB_1_6y_.cjs"),x=require("lucide-react"),n=require("react"),_e=require("./PDFSidebar-Di0D-yPS.cjs");function Be(f,h){const R=n.useRef(void 0);return n.useCallback((...I)=>{R.current&&clearTimeout(R.current),R.current=setTimeout(()=>f(...I),h)},[f,h])}function Ve({url:f,initialPage:h=1,initialScale:R=1,initialRotation:I=0,currentPage:J,onPageChange:C,scale:O,onScaleChange:w,rotation:$,onRotationChange:D,minScale:W=.5,maxScale:L=2.5,showToolbar:ue=!0,showSidebar:E=!0,showRotation:ae=!0,showModeToggle:xe=!0,showFullscreen:me=!0,enableHotkeys:Q=!0,enableMobileNav:de=!0,displayMode:fe="single",className:pe,toolbarClassName:je,contentClassName:he,contentHeight:Ee="80vh",pageClassName:H,workerUrl:q,cMapUrl:g,standardFontDataUrl:k,components:u,onLoadSuccess:P,onLoadError:p,onPageRender:v,loadingText:ve="正在加载PDF文档...",errorText:U="PDF加载失败"}){const[ee,G]=n.useState(null),[be,K]=n.useState(h),[Re,ge]=n.useState(R),[ke,ye]=n.useState(I),[Te,S]=n.useState(!1),[y,M]=n.useState(null),[m,_]=n.useState(0),[te,B]=n.useState(!1),[T,se]=n.useState(fe==="scroll"),[V,ne]=n.useState(E);n.useEffect(()=>{ne(E)},[E]);const[re,Ne]=n.useState(void 0),[ie,Ce]=n.useState(null),le=n.useRef(null),F=n.useRef(null),Z=n.useRef(new Map),i=J??be,j=O??Re,z=$??ke,b=J!==void 0,o=T,{Card:we,CardContent:De,Button:d,Input:Pe,Skeleton:Se}=u||{};n.useEffect(()=>{G(null),_(0),M(null),S(!1),b||K(Math.max(1,h))},[f,h,b]);const Me=n.useMemo(()=>{const e={withCredentials:!1};return g&&(e.cMapUrl=g,e.cMapPacked=!0),k&&(e.standardFontDataUrl=k),e},[g,k]);n.useEffect(()=>{let e=!0;return(async()=>{try{const l=await Promise.resolve().then(()=>require("./index-BiA_tnaq.cjs"));if(typeof window<"u"){const r=l.pdfjs,c=r==null?void 0:r.version;r!=null&&r.GlobalWorkerOptions&&c&&(q?r.GlobalWorkerOptions.workerSrc=q:r.GlobalWorkerOptions.workerSrc=`https://cdn.jsdelivr.net/npm/pdfjs-dist@${c}/build/pdf.worker.min.mjs`,!g&&r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.cMapUrl=`https://unpkg.com/pdfjs-dist@${c}/cmaps/`),!k&&r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.standardFontDataUrl=`https://unpkg.com/pdfjs-dist@${c}/standard_fonts/`))}e&&Ce(l)}catch(l){if(e){const r=l instanceof Error?l:new Error("无法加载 react-pdf 库");M(r),S(!1),p==null||p(r)}}})(),()=>{e=!1}},[q,g,k,p]);const Fe=n.useCallback(e=>{console.error("PDF加载失败:",e),console.error("PDF URL:",f),G(null),_(0),M(new Error(`${U}: ${e.message||"请检查文件路径或网络连接"}`)),S(!1),p==null||p(e)},[f,U,p]),ze=n.useCallback(e=>{G(e),_(e.numPages),M(null),S(!1),b||K(s=>Math.max(1,Math.min(s,Math.max(e.numPages,1)))),P==null||P(e)},[b,P]),a=n.useCallback(e=>{if(!Number.isFinite(e))return;const s=m>0?Math.max(1,Math.min(Math.trunc(e),m)):Math.max(1,Math.trunc(e));b||K(s),s!==i&&(C==null||C(s))},[m,b,i,C]),Ae=n.useCallback((e,s)=>{s?Z.current.set(e,s):Z.current.delete(e)},[]),Ie=n.useCallback(()=>{const e=F.current;if(!e||!o||m<=0)return;const s=e.getBoundingClientRect().top;let l=i,r=Number.POSITIVE_INFINITY;Z.current.forEach((c,A)=>{const oe=Math.abs(c.getBoundingClientRect().top-s);oe<r&&(r=oe,l=A)}),l!==i&&a(l)},[i,a,o,m]),N=n.useCallback(e=>{const s=Math.max(W,Math.min(L,j+e));O===void 0&&ge(s),w==null||w(s)},[j,W,L,O,w]),Oe=n.useCallback(()=>{const e=(z+90)%360;$===void 0&&ye(e),D==null||D(e)},[z,$,D]),ce=Be(e=>{Ne(e)},100);n.useEffect(()=>{if(!F.current)return;const e=F.current,s=()=>{ce(e.clientWidth)};s();const l=new ResizeObserver(()=>{s()});return l.observe(e),()=>{l.disconnect()}},[ce]),n.useEffect(()=>{if(!Q)return;const e=s=>{const l=s.target,r=typeof document<"u"?document.activeElement:null,c=l||r,A=c==null?void 0:c.getAttribute("role");c&&(c.tagName==="INPUT"||c.tagName==="TEXTAREA"||c.tagName==="SELECT"||c.isContentEditable||A==="textbox"||A==="spinbutton")||((s.ctrlKey||s.metaKey)&&(s.key==="="||s.key==="+")?(s.preventDefault(),N(.1)):(s.ctrlKey||s.metaKey)&&s.key==="-"?(s.preventDefault(),N(-.1)):!o&&s.key==="ArrowLeft"?(s.preventDefault(),a(i-1)):!o&&s.key==="ArrowRight"&&(s.preventDefault(),a(i+1)))};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[Q,i,a,o,N]);const $e=n.useCallback(async()=>{var e,s;if(!(typeof document>"u"))if(document.fullscreenElement)document.exitFullscreen&&(await document.exitFullscreen(),B(!1));else try{await((s=(e=le.current)==null?void 0:e.requestFullscreen)==null?void 0:s.call(e)),B(!0)}catch(l){console.error("Error attempting to enable fullscreen:",l)}},[]);n.useEffect(()=>{if(typeof document>"u")return;const e=()=>{B(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",e),()=>{document.removeEventListener("fullscreenchange",e)}},[]);const We=n.useCallback(e=>{a(e),se(!1)},[a]),Le=()=>ue?t.jsxRuntimeExports.jsxs("div",{className:`flex items-center justify-between gap-4 border-b px-4 py-2 ${je||""}`,children:[t.jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[E&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>ne(!V),title:V?"隐藏侧边栏":"显示侧边栏",children:t.jsxRuntimeExports.jsx(x.PanelLeft,{})}),t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>N(-.1),disabled:j<=W,children:t.jsxRuntimeExports.jsx(x.ZoomOut,{})}),t.jsxRuntimeExports.jsxs("span",{className:"min-w-[3rem] text-center text-sm",children:[Math.round(j*100),"%"]}),t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>N(.1),disabled:j>=L,children:t.jsxRuntimeExports.jsx(x.ZoomIn,{})}),ae&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:Oe,children:t.jsxRuntimeExports.jsx(x.RotateCw,{})}),xe&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>se(!T),title:T?"单页模式":"滚动模式",children:T?t.jsxRuntimeExports.jsx(x.ScrollText,{}):t.jsxRuntimeExports.jsx(x.FileText,{})}),me&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:$e,children:te?t.jsxRuntimeExports.jsx(x.Minimize2,{}):t.jsxRuntimeExports.jsx(x.Maximize2,{})})]}),t.jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[!o&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>a(i-1),disabled:i<=1,children:t.jsxRuntimeExports.jsx(x.ChevronLeft,{})}),t.jsxRuntimeExports.jsx(Pe,{type:"number",min:1,max:m,value:i,onChange:e=>a(parseInt(e.target.value)||1),disabled:o,readOnly:o,title:o?"滚动模式下页码仅显示当前位置":void 0,className:"w-16 text-center"}),t.jsxRuntimeExports.jsxs("span",{className:"text-sm text-muted-foreground",children:["/ ",m]}),!o&&t.jsxRuntimeExports.jsx(d,{variant:"outline",size:"icon",onClick:()=>a(i+1),disabled:m>0&&i>=m,children:t.jsxRuntimeExports.jsx(x.ChevronRight,{})})]})]}):null,X=()=>t.jsxRuntimeExports.jsx("div",{className:"flex h-full items-center justify-center",children:t.jsxRuntimeExports.jsx("p",{className:"text-muted-foreground",children:ve})}),Y=()=>t.jsxRuntimeExports.jsx("div",{className:"flex h-full min-h-[400px] items-center justify-center px-4 text-center text-destructive",children:t.jsxRuntimeExports.jsxs("div",{className:"max-w-md",children:[t.jsxRuntimeExports.jsx("p",{className:"mb-2 text-lg font-medium",children:"文件加载失败"}),t.jsxRuntimeExports.jsx("p",{className:"text-sm opacity-80",children:y==null?void 0:y.message})]})}),qe=()=>{if(!ie)return X();const{Document:e,Page:s}=ie;return t.jsxRuntimeExports.jsx("div",{ref:F,onScroll:o?Ie:void 0,className:`pdf-container flex-1 overflow-y-auto ${he||""}`,children:t.jsxRuntimeExports.jsx("div",{className:"flex min-h-full justify-center px-4",children:t.jsxRuntimeExports.jsx(e,{file:f,onLoadError:Fe,options:Me,loading:X(),error:Y(),onLoadSuccess:ze,children:y?Y():T?Array.from(new Array(m),(l,r)=>t.jsxRuntimeExports.jsx("div",{ref:c=>Ae(r+1,c),"data-page-number":r+1,className:`mb-4 ${H||""}`,children:t.jsxRuntimeExports.jsx(s,{pageNumber:r+1,renderTextLayer:!1,renderAnnotationLayer:!1,width:re,scale:j,rotate:z,onRenderSuccess:()=>v==null?void 0:v(r+1)})},`page_${r+1}`)):t.jsxRuntimeExports.jsx("div",{className:H||"",children:t.jsxRuntimeExports.jsx(s,{pageNumber:i,renderTextLayer:!1,renderAnnotationLayer:!1,width:re,scale:j,rotate:z,onRenderSuccess:()=>v==null?void 0:v(i)})})},f)})})},Ge=()=>{if(!E||!V||!ee)return null;const e=_e.PDFSidebar;return t.jsxRuntimeExports.jsx(e,{pdfDocument:ee,currentPage:i,onPageClick:We,components:{Tabs:u.Tabs,TabsList:u.TabsList,TabsTrigger:u.TabsTrigger,TabsContent:u.TabsContent,ScrollArea:u.ScrollArea,Skeleton:Se}})},Ke=()=>!de||o?null:t.jsxRuntimeExports.jsxs("div",{className:"fixed bottom-4 left-1/2 z-50 flex -translate-x-1/2 gap-2 md:hidden",children:[t.jsxRuntimeExports.jsxs(d,{variant:"secondary",size:"sm",onClick:()=>a(i-1),disabled:o||i<=1,title:o?"滚动模式下通过滚动定位页面":void 0,children:[t.jsxRuntimeExports.jsx(x.ChevronLeft,{}),t.jsxRuntimeExports.jsx("span",{className:"ml-1",children:"上一页"})]}),t.jsxRuntimeExports.jsxs(d,{variant:"secondary",size:"sm",onClick:()=>a(i+1),disabled:o||i>=m,title:o?"滚动模式下通过滚动定位页面":void 0,children:[t.jsxRuntimeExports.jsx("span",{className:"mr-1",children:"下一页"}),t.jsxRuntimeExports.jsx(x.ChevronRight,{})]})]});if(!u)return t.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});if(E){const e=[];if(u.Tabs||e.push("Tabs"),u.TabsList||e.push("TabsList"),u.TabsTrigger||e.push("TabsTrigger"),u.TabsContent||e.push("TabsContent"),u.ScrollArea||e.push("ScrollArea"),e.length>0){const s=e.length===1?e[0]:`${e.slice(0,-1).join("、")} 和 ${e[e.length-1]}`;return t.jsxRuntimeExports.jsxs("div",{className:"p-4 text-center text-destructive",children:["错误:侧边栏功能需要注入 ",s," 组件"]})}}return t.jsxRuntimeExports.jsxs("div",{ref:le,children:[t.jsxRuntimeExports.jsxs(we,{className:pe,children:[Le(),t.jsxRuntimeExports.jsx(De,{className:"p-0",style:{height:te?"100vh":Ee},children:t.jsxRuntimeExports.jsx("div",{className:"flex h-full flex-col",children:t.jsxRuntimeExports.jsxs("div",{className:"flex flex-1 overflow-hidden",children:[Ge(),Te?X():y?Y():qe()]})})})]}),Ke()]})}exports.PDFReader=Ve;
1
+ "use strict";var Be=Object.create;var ce=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var Je=(l,u,f,v)=>{if(u&&typeof u=="object"||typeof u=="function")for(let h of Ze(u))!Ye.call(l,h)&&h!==f&&ce(l,h,{get:()=>u[h],enumerable:!(v=Ve(u,h))||v.enumerable});return l};var Qe=(l,u,f)=>(f=l!=null?Be(Xe(l)):{},Je(u||!l||!l.__esModule?ce(f,"default",{value:l,enumerable:!0}):f,l));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./jsx-runtime-BB_1_6y_.cjs"),d=require("lucide-react"),n=require("react"),He=require("./PDFSidebar-4DtXqqzN.cjs");function Ue(l,u){const f=n.useRef(void 0);return n.useCallback((...v)=>{f.current&&clearTimeout(f.current),f.current=setTimeout(()=>l(...v),u)},[l,u])}function et({url:l,initialPage:u=1,initialScale:f=1,initialRotation:v=0,currentPage:h,onPageChange:D,scale:L,onScaleChange:M,rotation:G,onRotationChange:P,minScale:q=.5,maxScale:K=2.5,showToolbar:ue=!0,showSidebar:R=!0,showRotation:xe=!0,showModeToggle:me=!0,showFullscreen:de=!0,enableHotkeys:H=!0,enableMobileNav:fe=!0,displayMode:pe="single",className:je,toolbarClassName:he,contentClassName:be,contentHeight:Ee="80vh",pageClassName:U,workerUrl:_,cMapUrl:T,standardFontDataUrl:N,components:x,onLoadSuccess:S,onLoadError:b,onPageRender:g,loadingText:ve="正在加载PDF文档...",errorText:ee="PDF加载失败"}){const[te,B]=n.useState(null),[Re,V]=n.useState(u),[ge,ke]=n.useState(f),[ye,Te]=n.useState(v),[Ne,F]=n.useState(!1),[C,z]=n.useState(null),[p,Z]=n.useState(0),[A,X]=n.useState(!1),[k,se]=n.useState(pe==="scroll"),[I,ne]=n.useState(R);n.useEffect(()=>{ne(R)},[R]);const[re,Ce]=n.useState(void 0),[ie,we]=n.useState(null),le=n.useRef(null),O=n.useRef(null),Y=n.useRef(new Map),i=h??Re,E=L??ge,$=G??ye,y=h!==void 0,c=k,{Card:De,CardContent:Me,Button:j,Input:Pe,Skeleton:Se}=x||{};n.useEffect(()=>{B(null),Z(0),z(null),F(!1),y||V(Math.max(1,u))},[l,u,y]);const Fe=n.useMemo(()=>{const e={withCredentials:!1};return T&&(e.cMapUrl=T,e.cMapPacked=!0),N&&(e.standardFontDataUrl=N),e},[T,N]);n.useEffect(()=>{let e=!0;return(async()=>{try{const a=await import("react-pdf");if(typeof window<"u"){const r=a.pdfjs,o=r==null?void 0:r.version;r!=null&&r.GlobalWorkerOptions&&o&&(_?r.GlobalWorkerOptions.workerSrc=_:r.GlobalWorkerOptions.workerSrc=`https://cdn.jsdelivr.net/npm/pdfjs-dist@${o}/build/pdf.worker.min.mjs`,!T&&r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.cMapUrl=`https://unpkg.com/pdfjs-dist@${o}/cmaps/`),!N&&r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.standardFontDataUrl=`https://unpkg.com/pdfjs-dist@${o}/standard_fonts/`))}e&&we(a)}catch(a){if(e){const r=a instanceof Error?a:new Error("无法加载 react-pdf 库");z(r),F(!1),b==null||b(r)}}})(),()=>{e=!1}},[_,T,N,b]);const ze=n.useCallback(e=>{console.error("PDF加载失败:",e),console.error("PDF URL:",l),B(null),Z(0),z(new Error(`${ee}: ${e.message||"请检查文件路径或网络连接"}`)),F(!1),b==null||b(e)},[l,ee,b]),Ae=n.useCallback(e=>{B(e),Z(e.numPages),z(null),F(!1),y||V(s=>Math.max(1,Math.min(s,Math.max(e.numPages,1)))),S==null||S(e)},[y,S]),m=n.useCallback(e=>{if(!Number.isFinite(e))return;const s=p>0?Math.max(1,Math.min(Math.trunc(e),p)):Math.max(1,Math.trunc(e));y||V(s),s!==i&&(D==null||D(s))},[p,y,i,D]),Ie=n.useCallback((e,s)=>{s?Y.current.set(e,s):Y.current.delete(e)},[]),Oe=n.useCallback(()=>{const e=O.current;if(!e||!c||p<=0)return;const s=e.getBoundingClientRect().top;let a=i,r=Number.POSITIVE_INFINITY;Y.current.forEach((o,W)=>{const oe=Math.abs(o.getBoundingClientRect().top-s);oe<r&&(r=oe,a=W)}),a!==i&&m(a)},[i,m,c,p]),w=n.useCallback(e=>{const s=Math.max(q,Math.min(K,E+e));L===void 0&&ke(s),M==null||M(s)},[E,q,K,L,M]),$e=n.useCallback(()=>{const e=($+90)%360;G===void 0&&Te(e),P==null||P(e)},[$,G,P]),ae=Ue(e=>{Ce(e)},100);n.useEffect(()=>{if(!O.current)return;const e=O.current,s=()=>{ae(e.clientWidth)};s();const a=new ResizeObserver(()=>{s()});return a.observe(e),()=>{a.disconnect()}},[ae]),n.useEffect(()=>{if(!H)return;const e=s=>{const a=s.target,r=typeof document<"u"?document.activeElement:null,o=a||r,W=o==null?void 0:o.getAttribute("role");o&&(o.tagName==="INPUT"||o.tagName==="TEXTAREA"||o.tagName==="SELECT"||o.isContentEditable||W==="textbox"||W==="spinbutton")||((s.ctrlKey||s.metaKey)&&(s.key==="="||s.key==="+")?(s.preventDefault(),w(.1)):(s.ctrlKey||s.metaKey)&&s.key==="-"?(s.preventDefault(),w(-.1)):!c&&s.key==="ArrowLeft"?(s.preventDefault(),m(i-1)):!c&&s.key==="ArrowRight"&&(s.preventDefault(),m(i+1)))};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[H,i,m,c,w]);const We=n.useCallback(async()=>{var e,s;if(!(typeof document>"u"))if(document.fullscreenElement)document.exitFullscreen&&(await document.exitFullscreen(),X(!1));else try{await((s=(e=le.current)==null?void 0:e.requestFullscreen)==null?void 0:s.call(e)),X(!0)}catch(a){console.error("Error attempting to enable fullscreen:",a)}},[]);n.useEffect(()=>{if(typeof document>"u")return;const e=()=>{X(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",e),()=>{document.removeEventListener("fullscreenchange",e)}},[]);const Le=n.useCallback(e=>{m(e),se(!1)},[m]),Ge=()=>ue?t.jsxRuntimeExports.jsxs("div",{className:`flex items-center justify-between gap-4 border-b px-4 py-2 ${he||""}`,children:[t.jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[R&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>ne(!I),"aria-label":I?"隐藏侧边栏":"显示侧边栏",title:I?"隐藏侧边栏":"显示侧边栏",children:t.jsxRuntimeExports.jsx(d.PanelLeft,{})}),t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>w(-.1),disabled:E<=q,"aria-label":"缩小",title:"缩小",children:t.jsxRuntimeExports.jsx(d.ZoomOut,{})}),t.jsxRuntimeExports.jsxs("span",{className:"min-w-[3rem] text-center text-sm",children:[Math.round(E*100),"%"]}),t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>w(.1),disabled:E>=K,"aria-label":"放大",title:"放大",children:t.jsxRuntimeExports.jsx(d.ZoomIn,{})}),xe&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:$e,"aria-label":"顺时针旋转",title:"顺时针旋转",children:t.jsxRuntimeExports.jsx(d.RotateCw,{})}),me&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>se(!k),"aria-label":k?"切换到单页模式":"切换到滚动模式",title:k?"单页模式":"滚动模式",children:k?t.jsxRuntimeExports.jsx(d.ScrollText,{}):t.jsxRuntimeExports.jsx(d.FileText,{})}),de&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:We,"aria-label":A?"退出全屏":"进入全屏",title:A?"退出全屏":"进入全屏",children:A?t.jsxRuntimeExports.jsx(d.Minimize2,{}):t.jsxRuntimeExports.jsx(d.Maximize2,{})})]}),t.jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[!c&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>m(i-1),disabled:i<=1,"aria-label":"上一页",title:"上一页",children:t.jsxRuntimeExports.jsx(d.ChevronLeft,{})}),t.jsxRuntimeExports.jsx(Pe,{type:"number",name:"pdf-page",min:1,max:p,value:i,onChange:e=>m(parseInt(e.target.value)||1),disabled:c,readOnly:c,"aria-label":"当前页码",inputMode:"numeric",autoComplete:"off",title:c?"滚动模式下页码仅显示当前位置":void 0,className:"w-16 text-center"}),t.jsxRuntimeExports.jsxs("span",{className:"text-sm text-muted-foreground",children:["/ ",p]}),!c&&t.jsxRuntimeExports.jsx(j,{variant:"outline",size:"icon",onClick:()=>m(i+1),disabled:p>0&&i>=p,"aria-label":"下一页",title:"下一页",children:t.jsxRuntimeExports.jsx(d.ChevronRight,{})})]})]}):null,J=()=>t.jsxRuntimeExports.jsx("div",{className:"flex h-full items-center justify-center",role:"status","aria-live":"polite",children:t.jsxRuntimeExports.jsx("p",{className:"text-muted-foreground",children:ve})}),Q=()=>t.jsxRuntimeExports.jsx("div",{className:"flex h-full min-h-[400px] items-center justify-center px-4 text-center text-destructive",role:"alert",children:t.jsxRuntimeExports.jsxs("div",{className:"max-w-md",children:[t.jsxRuntimeExports.jsx("p",{className:"mb-2 text-lg font-medium",children:"文件加载失败"}),t.jsxRuntimeExports.jsx("p",{className:"text-sm opacity-80",children:C==null?void 0:C.message})]})}),qe=()=>{if(!ie)return J();const{Document:e,Page:s}=ie;return t.jsxRuntimeExports.jsx("div",{ref:O,onScroll:c?Oe:void 0,className:`pdf-container flex-1 overflow-y-auto ${be||""}`,children:t.jsxRuntimeExports.jsx("div",{className:"flex min-h-full justify-center px-4",children:t.jsxRuntimeExports.jsx(e,{file:l,onLoadError:ze,options:Fe,loading:J(),error:Q(),onLoadSuccess:Ae,children:C?Q():k?Array.from(new Array(p),(a,r)=>t.jsxRuntimeExports.jsx("div",{ref:o=>Ie(r+1,o),"data-page-number":r+1,className:`mb-4 ${U||""}`,children:t.jsxRuntimeExports.jsx(s,{pageNumber:r+1,renderTextLayer:!1,renderAnnotationLayer:!1,width:re,scale:E,rotate:$,onRenderSuccess:()=>g==null?void 0:g(r+1)})},`page_${r+1}`)):t.jsxRuntimeExports.jsx("div",{className:U||"",children:t.jsxRuntimeExports.jsx(s,{pageNumber:i,renderTextLayer:!1,renderAnnotationLayer:!1,width:re,scale:E,rotate:$,onRenderSuccess:()=>g==null?void 0:g(i)})})},l)})})},Ke=()=>{if(!R||!I||!te)return null;const e=He.PDFSidebar;return t.jsxRuntimeExports.jsx(e,{pdfDocument:te,currentPage:i,onPageClick:Le,components:{Tabs:x.Tabs,TabsList:x.TabsList,TabsTrigger:x.TabsTrigger,TabsContent:x.TabsContent,ScrollArea:x.ScrollArea,Skeleton:Se}})},_e=()=>!fe||c?null:t.jsxRuntimeExports.jsxs("div",{className:"fixed bottom-4 left-1/2 z-50 flex -translate-x-1/2 gap-2 md:hidden",children:[t.jsxRuntimeExports.jsxs(j,{variant:"secondary",size:"sm",onClick:()=>m(i-1),disabled:c||i<=1,title:c?"滚动模式下通过滚动定位页面":void 0,children:[t.jsxRuntimeExports.jsx(d.ChevronLeft,{}),t.jsxRuntimeExports.jsx("span",{className:"ml-1",children:"上一页"})]}),t.jsxRuntimeExports.jsxs(j,{variant:"secondary",size:"sm",onClick:()=>m(i+1),disabled:c||i>=p,title:c?"滚动模式下通过滚动定位页面":void 0,children:[t.jsxRuntimeExports.jsx("span",{className:"mr-1",children:"下一页"}),t.jsxRuntimeExports.jsx(d.ChevronRight,{})]})]});if(!x)return t.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});if(R){const e=[];if(x.Tabs||e.push("Tabs"),x.TabsList||e.push("TabsList"),x.TabsTrigger||e.push("TabsTrigger"),x.TabsContent||e.push("TabsContent"),x.ScrollArea||e.push("ScrollArea"),e.length>0){const s=e.length===1?e[0]:`${e.slice(0,-1).join("、")} 和 ${e[e.length-1]}`;return t.jsxRuntimeExports.jsxs("div",{className:"p-4 text-center text-destructive",children:["错误:侧边栏功能需要注入 ",s," 组件"]})}}return t.jsxRuntimeExports.jsxs("div",{ref:le,children:[t.jsxRuntimeExports.jsxs(De,{className:je,children:[Ge(),t.jsxRuntimeExports.jsx(Me,{className:"p-0",style:{height:A?"100vh":Ee},children:t.jsxRuntimeExports.jsx("div",{className:"flex h-full flex-col",children:t.jsxRuntimeExports.jsxs("div",{className:"flex flex-1 overflow-hidden",children:[Ke(),Ne?J():C?Q():qe()]})})})]}),_e()]})}exports.PDFReader=et;
2
2
  //# sourceMappingURL=pdf-reader.cjs.map
@@ -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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"}