@eternalheart/react-file-preview 1.3.9 → 1.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/README.zh-CN.md +10 -0
- package/lib/FilePreviewContent.d.ts.map +1 -1
- package/lib/RequestContext.d.ts +1 -1
- package/lib/RequestContext.d.ts.map +1 -1
- package/lib/chunks/RendererError-BH6fzLrN.mjs +15 -0
- package/lib/chunks/RendererError-BH6fzLrN.mjs.map +1 -0
- package/lib/chunks/avifLoader-BP3fgcMm-BnpxLhxp.mjs +56 -0
- package/lib/chunks/avifLoader-BP3fgcMm-BnpxLhxp.mjs.map +1 -0
- package/lib/chunks/heicLoader-CH_raQNn-1fBLaICM.mjs +37 -0
- package/lib/chunks/heicLoader-CH_raQNn-1fBLaICM.mjs.map +1 -0
- package/lib/chunks/index-B57rEPin.mjs +54 -0
- package/lib/chunks/index-B57rEPin.mjs.map +1 -0
- package/lib/chunks/index-BCuRRLYt.mjs +222 -0
- package/lib/chunks/index-BCuRRLYt.mjs.map +1 -0
- package/lib/chunks/{index-BSD3w5eG.mjs → index-BJ6vTNxc.mjs} +76 -75
- package/lib/chunks/index-BJ6vTNxc.mjs.map +1 -0
- package/lib/chunks/index-BYdqrqnR.mjs +161 -0
- package/lib/chunks/index-BYdqrqnR.mjs.map +1 -0
- package/lib/chunks/index-BiyghBxu.mjs +136 -0
- package/lib/chunks/index-BiyghBxu.mjs.map +1 -0
- package/lib/chunks/{index-DdOEWhrk.mjs → index-C8CyS_sj.mjs} +66 -63
- package/lib/chunks/index-C8CyS_sj.mjs.map +1 -0
- package/lib/chunks/index-C8OrFLd5.mjs +594 -0
- package/lib/chunks/index-C8OrFLd5.mjs.map +1 -0
- package/lib/chunks/{index-DGuiWJr7.mjs → index-CCkHAeLh.mjs} +40 -37
- package/lib/chunks/index-CCkHAeLh.mjs.map +1 -0
- package/lib/chunks/index-CdmkF0CO.mjs +105 -0
- package/lib/chunks/index-CdmkF0CO.mjs.map +1 -0
- package/lib/chunks/index-CuAALtwC.mjs +2299 -0
- package/lib/chunks/index-CuAALtwC.mjs.map +1 -0
- package/lib/chunks/index-D660ENHx.mjs +114 -0
- package/lib/chunks/index-D660ENHx.mjs.map +1 -0
- package/lib/chunks/{index-DV5Jd7Qe.mjs → index-DBEG73K1.mjs} +79 -78
- package/lib/chunks/index-DBEG73K1.mjs.map +1 -0
- package/lib/chunks/index-DaFlk9dd.mjs +13097 -0
- package/lib/chunks/index-DaFlk9dd.mjs.map +1 -0
- package/lib/chunks/index-_mP0FkqE.mjs +113 -0
- package/lib/chunks/index-_mP0FkqE.mjs.map +1 -0
- package/lib/chunks/{index-U3w45GW8.mjs → index-nLTQXCV7.mjs} +84 -82
- package/lib/chunks/index-nLTQXCV7.mjs.map +1 -0
- package/lib/chunks/index-nVblatyi.mjs +55 -0
- package/lib/chunks/index-nVblatyi.mjs.map +1 -0
- package/lib/chunks/{index-zEVVgWCH.mjs → index-ow-nGpuu.mjs} +99 -98
- package/lib/chunks/index-ow-nGpuu.mjs.map +1 -0
- package/lib/chunks/index-qOC5xQyK.mjs +96 -0
- package/lib/chunks/index-qOC5xQyK.mjs.map +1 -0
- package/lib/chunks/index-rUfsiVR8.mjs +12335 -0
- package/lib/chunks/index-rUfsiVR8.mjs.map +1 -0
- package/lib/chunks/jp2Loader-Bn-qPMbD-Bn-qPMbD.mjs +122 -0
- package/lib/chunks/jp2Loader-Bn-qPMbD-Bn-qPMbD.mjs.map +1 -0
- package/lib/chunks/psdLoader-Doxw3mWm-DVOGFSlh.mjs +73 -0
- package/lib/chunks/psdLoader-Doxw3mWm-DVOGFSlh.mjs.map +1 -0
- package/lib/chunks/rawLoader-0mLvxCNp-CJmERiK7.mjs +82 -0
- package/lib/chunks/rawLoader-0mLvxCNp-CJmERiK7.mjs.map +1 -0
- package/lib/chunks/tiffLoader-CTFKVLqJ-B84NfwhR.mjs +60 -0
- package/lib/chunks/tiffLoader-CTFKVLqJ-B84NfwhR.mjs.map +1 -0
- package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs → useShikiHighlight-ClbUXJ2p.mjs} +3 -3
- package/lib/chunks/{useShikiHighlight-DzEAK0S7.mjs.map → useShikiHighlight-ClbUXJ2p.mjs.map} +1 -1
- package/lib/index.cjs +33 -20
- package/lib/index.cjs.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.mjs +14 -13
- package/lib/renderers/Audio/index.d.ts.map +1 -1
- package/lib/renderers/Csv/index.d.ts.map +1 -1
- package/lib/renderers/Docx/index.d.ts.map +1 -1
- package/lib/renderers/Epub/index.d.ts.map +1 -1
- package/lib/renderers/Font/index.d.ts +6 -0
- package/lib/renderers/Font/index.d.ts.map +1 -0
- package/lib/renderers/Image/index.d.ts +2 -0
- package/lib/renderers/Image/index.d.ts.map +1 -1
- package/lib/renderers/Json/index.d.ts.map +1 -1
- package/lib/renderers/Markdown/index.d.ts.map +1 -1
- package/lib/renderers/Mobi/index.d.ts.map +1 -1
- package/lib/renderers/Msg/index.d.ts.map +1 -1
- package/lib/renderers/Pdf/index.d.ts +0 -1
- package/lib/renderers/Pdf/index.d.ts.map +1 -1
- package/lib/renderers/Pptx/index.d.ts.map +1 -1
- package/lib/renderers/RendererError.d.ts +8 -0
- package/lib/renderers/RendererError.d.ts.map +1 -0
- package/lib/renderers/Subtitle/index.d.ts.map +1 -1
- package/lib/renderers/Text/index.d.ts.map +1 -1
- package/lib/renderers/Video/index.d.ts +1 -0
- package/lib/renderers/Video/index.d.ts.map +1 -1
- package/lib/renderers/Xlsx/index.d.ts.map +1 -1
- package/lib/renderers/Xml/index.d.ts.map +1 -1
- package/lib/renderers/Zip/index.d.ts.map +1 -1
- package/lib/renderers/lazy.d.ts +2 -0
- package/lib/renderers/lazy.d.ts.map +1 -1
- package/lib/utils/pdfConfig.d.ts +2 -2
- package/lib/utils/pdfConfig.d.ts.map +1 -1
- package/package.json +14 -5
- package/lib/chunks/index-B-H9HQiI.mjs +0 -110
- package/lib/chunks/index-B-H9HQiI.mjs.map +0 -1
- package/lib/chunks/index-BGeyzo6u.mjs +0 -96
- package/lib/chunks/index-BGeyzo6u.mjs.map +0 -1
- package/lib/chunks/index-BNUiNUWa.mjs +0 -103
- package/lib/chunks/index-BNUiNUWa.mjs.map +0 -1
- package/lib/chunks/index-BSD3w5eG.mjs.map +0 -1
- package/lib/chunks/index-BcBe6KW7.mjs +0 -99
- package/lib/chunks/index-BcBe6KW7.mjs.map +0 -1
- package/lib/chunks/index-BdYkTSTt.mjs +0 -51
- package/lib/chunks/index-BdYkTSTt.mjs.map +0 -1
- package/lib/chunks/index-BqEuP_8r.mjs +0 -152
- package/lib/chunks/index-BqEuP_8r.mjs.map +0 -1
- package/lib/chunks/index-Bv93wiEK.mjs +0 -2031
- package/lib/chunks/index-Bv93wiEK.mjs.map +0 -1
- package/lib/chunks/index-CKirCT35.mjs +0 -52
- package/lib/chunks/index-CKirCT35.mjs.map +0 -1
- package/lib/chunks/index-CgV8T0G5.mjs +0 -257
- package/lib/chunks/index-CgV8T0G5.mjs.map +0 -1
- package/lib/chunks/index-D8GtNeDn.mjs +0 -116
- package/lib/chunks/index-D8GtNeDn.mjs.map +0 -1
- package/lib/chunks/index-DGuiWJr7.mjs.map +0 -1
- package/lib/chunks/index-DV5Jd7Qe.mjs.map +0 -1
- package/lib/chunks/index-DdOEWhrk.mjs.map +0 -1
- package/lib/chunks/index-DmepcY31.mjs +0 -96
- package/lib/chunks/index-DmepcY31.mjs.map +0 -1
- package/lib/chunks/index-U3w45GW8.mjs.map +0 -1
- package/lib/chunks/index-r3q2xCCI.mjs +0 -129
- package/lib/chunks/index-r3q2xCCI.mjs.map +0 -1
- package/lib/chunks/index-zEVVgWCH.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -304,6 +304,10 @@ const files = [
|
|
|
304
304
|
- **Excel**: XLSX format support
|
|
305
305
|
- **PowerPoint**: PPTX/PPT format support, slide preview
|
|
306
306
|
|
|
307
|
+
### Fonts
|
|
308
|
+
- **Formats**: TTF, OTF, WOFF, WOFF2
|
|
309
|
+
- **Features**: Font metadata (family, designer, version), character set preview, custom text input, multi-size display
|
|
310
|
+
|
|
307
311
|
### Code & Text
|
|
308
312
|
- **Markdown**: GitHub Flavored Markdown, code highlighting
|
|
309
313
|
- **Code Files**: JS, TS, Python, Java, C++, Go, Rust, and 40+ languages
|
|
@@ -442,6 +446,12 @@ const files = [
|
|
|
442
446
|
#### Other Documents
|
|
443
447
|
- **PDF**: `application/pdf`
|
|
444
448
|
|
|
449
|
+
#### Fonts
|
|
450
|
+
- **TrueType**: `application/x-font-ttf`, `font/ttf` (.ttf)
|
|
451
|
+
- **OpenType**: `application/x-font-otf`, `font/otf` (.otf)
|
|
452
|
+
- **WOFF**: `application/font-woff`, `font/woff` (.woff)
|
|
453
|
+
- **WOFF2**: `application/font-woff2`, `font/woff2` (.woff2)
|
|
454
|
+
|
|
445
455
|
#### Media Files
|
|
446
456
|
- **Images**: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml`, etc.
|
|
447
457
|
- **Videos**: `video/mp4`, `video/webm`, `video/ogg`, etc.
|
package/README.zh-CN.md
CHANGED
|
@@ -302,6 +302,10 @@ const files = [
|
|
|
302
302
|
- **Excel**: XLSX 格式支持
|
|
303
303
|
- **PowerPoint**: PPTX/PPT 格式支持、幻灯片预览
|
|
304
304
|
|
|
305
|
+
### 字体
|
|
306
|
+
- **格式**: TTF, OTF, WOFF, WOFF2
|
|
307
|
+
- **功能**: 字体元数据(字体家族、设计师、版本)、字符集预览、自定义文本输入、多字号展示
|
|
308
|
+
|
|
305
309
|
### 代码 & 文本
|
|
306
310
|
- **Markdown**: GitHub Flavored Markdown,代码高亮
|
|
307
311
|
- **代码文件**: JS, TS, Python, Java, C++, Go, Rust 等 40+ 种语言
|
|
@@ -440,6 +444,12 @@ const files = [
|
|
|
440
444
|
#### 其他文档
|
|
441
445
|
- **PDF**: `application/pdf`
|
|
442
446
|
|
|
447
|
+
#### 字体
|
|
448
|
+
- **TrueType**: `application/x-font-ttf`, `font/ttf` (.ttf)
|
|
449
|
+
- **OpenType**: `application/x-font-otf`, `font/otf` (.otf)
|
|
450
|
+
- **WOFF**: `application/font-woff`, `font/woff` (.woff)
|
|
451
|
+
- **WOFF2**: `application/font-woff2`, `font/woff2` (.woff2)
|
|
452
|
+
|
|
443
453
|
#### 媒体文件
|
|
444
454
|
- **图片**: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml`, 等
|
|
445
455
|
- **视频**: `video/mp4`, `video/webm`, `video/ogg`, 等
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAiCtJ,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC5D,qDAAqD;IACrD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,oEAAoE;IACpE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAWhE,CAAC"}
|
package/lib/RequestContext.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare function useRequest(): RequestContextValue;
|
|
|
15
15
|
export declare function useFetcher(): Fetcher;
|
|
16
16
|
/**
|
|
17
17
|
* 解析 file 的可消费 URL:
|
|
18
|
-
* - 未配置 shouldFetchAsBlob 或返回 false
|
|
18
|
+
* - 未配置 shouldFetchAsBlob 或返回 false:同步返回 file.url(不入 state,避免切换文件时残留旧值)
|
|
19
19
|
* - 返回 true:用 fetcher 拉成 blob: URL,组件卸载或 file 变化时 revoke
|
|
20
20
|
*
|
|
21
21
|
* 期间返回空字符串(表示 "还没准备好"),调用方应避免空 URL 时挂载到 <img src> 等。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../src/RequestContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,iCAAiC,CAAC;AAGzC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAQD,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgB1D,CAAC;AAEF,wBAAgB,UAAU,IAAI,mBAAmB,CAEhD;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../src/RequestContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,iCAAiC,CAAC;AAGzC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAQD,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgB1D,CAAC;AAEF,wBAAgB,UAAU,IAAI,mBAAmB,CAEhD;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAuDpE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as r, jsxs as p } from "react/jsx-runtime";
|
|
2
|
+
import { AlertCircle as l } from "lucide-react";
|
|
3
|
+
const c = ({
|
|
4
|
+
message: f,
|
|
5
|
+
detail: e,
|
|
6
|
+
showIcon: t = !0
|
|
7
|
+
}) => /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ p("div", { className: "rfp-text-center", children: [
|
|
8
|
+
t && /* @__PURE__ */ r("div", { className: "rfp-w-16 rfp-h-16 rfp-mx-auto rfp-mb-4 rfp-rounded-full rfp-bg-red-500/10 rfp-flex rfp-items-center rfp-justify-center", children: /* @__PURE__ */ r(l, { className: "rfp-w-8 rfp-h-8 rfp-text-red-400" }) }),
|
|
9
|
+
/* @__PURE__ */ r("p", { className: "rfp-text-lg md:rfp-text-xl rfp-font-medium rfp-text-fg-primary rfp-mb-2", children: f }),
|
|
10
|
+
e && /* @__PURE__ */ r("p", { className: "rfp-text-sm rfp-text-fg-tertiary", children: e })
|
|
11
|
+
] }) });
|
|
12
|
+
export {
|
|
13
|
+
c as R
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=RendererError-BH6fzLrN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RendererError-BH6fzLrN.mjs","sources":["../../src/renderers/RendererError.tsx"],"sourcesContent":["import { AlertCircle } from 'lucide-react';\n\ninterface RendererErrorProps {\n message: string;\n detail?: string;\n showIcon?: boolean;\n}\n\nexport const RendererError: React.FC<RendererErrorProps> = ({\n message,\n detail,\n showIcon = true,\n}) => {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-text-center\">\n {showIcon && (\n <div className=\"rfp-w-16 rfp-h-16 rfp-mx-auto rfp-mb-4 rfp-rounded-full rfp-bg-red-500/10 rfp-flex rfp-items-center rfp-justify-center\">\n <AlertCircle className=\"rfp-w-8 rfp-h-8 rfp-text-red-400\" />\n </div>\n )}\n <p className=\"rfp-text-lg md:rfp-text-xl rfp-font-medium rfp-text-fg-primary rfp-mb-2\">\n {message}\n </p>\n {detail && (\n <p className=\"rfp-text-sm rfp-text-fg-tertiary\">{detail}</p>\n )}\n </div>\n </div>\n );\n};\n"],"names":["RendererError","message","detail","showIcon","jsxs","jsx","AlertCircle"],"mappings":";;AAQO,MAAMA,IAA8C,CAAC;AAAA,EAC1D,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC,IAAW;AACb,wBAEK,OAAA,EAAI,WAAU,sEACb,UAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,mBACZ,UAAA;AAAA,EAAAD,KACC,gBAAAE,EAAC,SAAI,WAAU,0HACb,4BAACC,GAAA,EAAY,WAAU,oCAAmC,EAAA,CAC5D;AAAA,EAEF,gBAAAD,EAAC,KAAA,EAAE,WAAU,2EACV,UAAAJ,GACH;AAAA,EACCC,KACC,gBAAAG,EAAC,KAAA,EAAE,WAAU,oCAAoC,UAAAH,EAAA,CAAO;AAAA,EAAA,CAE5D,EAAA,CACF;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
let a = null;
|
|
2
|
+
async function B() {
|
|
3
|
+
return a !== null ? a : new Promise((n) => {
|
|
4
|
+
const A = new Image();
|
|
5
|
+
A.onload = () => {
|
|
6
|
+
a = A.width === 1 && A.height === 1, n(a);
|
|
7
|
+
}, A.onerror = () => {
|
|
8
|
+
a = !1, n(!1);
|
|
9
|
+
}, A.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=";
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
class d {
|
|
13
|
+
/**
|
|
14
|
+
* 检测是否需要解码:仅在浏览器不原生支持 AVIF 时需要
|
|
15
|
+
*/
|
|
16
|
+
async needsDecode(A) {
|
|
17
|
+
return A !== "image/avif" ? !1 : !await B();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 解码 AVIF 文件为 PNG Blob
|
|
21
|
+
*/
|
|
22
|
+
async decode(A, r) {
|
|
23
|
+
if (await B())
|
|
24
|
+
return A instanceof Blob ? A : new Blob([A], { type: "image/avif" });
|
|
25
|
+
try {
|
|
26
|
+
const e = await import("@jsquash/avif"), l = A instanceof Blob ? await A.arrayBuffer() : A, o = await e.decode(l), t = document.createElement("canvas");
|
|
27
|
+
t.width = o.width, t.height = o.height;
|
|
28
|
+
const i = t.getContext("2d");
|
|
29
|
+
if (!i)
|
|
30
|
+
throw new Error("无法创建 Canvas 2D 上下文");
|
|
31
|
+
return i.putImageData(o, 0, 0), new Promise((c, g) => {
|
|
32
|
+
t.toBlob(
|
|
33
|
+
(s) => {
|
|
34
|
+
s ? c(s) : g(new Error("AVIF Canvas 转换为 PNG 失败"));
|
|
35
|
+
},
|
|
36
|
+
(r == null ? void 0 : r.outputFormat) || "image/png"
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw new Error(`AVIF 解码失败: ${(e == null ? void 0 : e.message) || "未知错误"}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 获取 AVIF 元数据
|
|
45
|
+
*/
|
|
46
|
+
async getMetadata(A) {
|
|
47
|
+
return {
|
|
48
|
+
format: "avif"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const w = new d();
|
|
53
|
+
export {
|
|
54
|
+
w as default
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=avifLoader-BP3fgcMm-BnpxLhxp.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avifLoader-BP3fgcMm-BnpxLhxp.mjs","sources":["../../../file-preview-core/lib/avifLoader-BP3fgcMm.js"],"sourcesContent":["let e = null;\nasync function c() {\n return e !== null ? e : new Promise((n) => {\n const A = new Image();\n A.onload = () => {\n e = A.width === 1 && A.height === 1, n(e);\n }, A.onerror = () => {\n e = !1, n(!1);\n }, A.src = \"data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=\";\n });\n}\nclass f {\n /**\n * 检测是否需要解码:仅在浏览器不原生支持 AVIF 时需要\n */\n async needsDecode(A) {\n return A !== \"image/avif\" ? !1 : !await c();\n }\n /**\n * 解码 AVIF 文件为 PNG Blob\n */\n async decode(A, r) {\n if (await c())\n return A instanceof Blob ? A : new Blob([A], { type: \"image/avif\" });\n try {\n const a = await import(\"@jsquash/avif\"), i = A instanceof Blob ? await A.arrayBuffer() : A, o = await a.decode(i), t = document.createElement(\"canvas\");\n t.width = o.width, t.height = o.height;\n const s = t.getContext(\"2d\");\n if (!s)\n throw new Error(\"无法创建 Canvas 2D 上下文\");\n return s.putImageData(o, 0, 0), new Promise((g, d) => {\n t.toBlob(\n (B) => {\n B ? g(B) : d(new Error(\"AVIF Canvas 转换为 PNG 失败\"));\n },\n (r == null ? void 0 : r.outputFormat) || \"image/png\"\n );\n });\n } catch (a) {\n throw new Error(`AVIF 解码失败: ${(a == null ? void 0 : a.message) || \"未知错误\"}`);\n }\n }\n /**\n * 获取 AVIF 元数据\n */\n async getMetadata(A) {\n return {\n format: \"avif\"\n };\n }\n}\nconst m = new f();\nexport {\n m as default\n};\n//# sourceMappingURL=avifLoader-BP3fgcMm.js.map\n"],"names":["e","c","f","a","i","s","g","d","B","m"],"mappings":"AAAA,IAAIA,IAAI;AACR,eAAeC,IAAI;AACjB,SAAOD,MAAM,OAAOA,IAAI,IAAI,QAAQ,CAAC,MAAM;AACzC,UAAM,IAAI,IAAI,MAAK;AACnB,MAAE,SAAS,MAAM;AACf,MAAAA,IAAI,EAAE,UAAU,KAAK,EAAE,WAAW,GAAG,EAAEA,CAAC;AAAA,IAC1C,GAAG,EAAE,UAAU,MAAM;AACnB,MAAAA,IAAI,IAAI,EAAE,EAAE;AAAA,IACd,GAAG,EAAE,MAAM;AAAA,EACb,CAAC;AACH;AACA,MAAME,EAAE;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM,YAAY,GAAG;AACnB,WAAO,MAAM,eAAe,KAAK,CAAC,MAAMD,EAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM,OAAO,GAAG,GAAG;AACjB,QAAI,MAAMA,EAAC;AACT,aAAO,aAAa,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,cAAc;AACrE,QAAI;AACF,YAAME,IAAI,MAAM,OAAO,eAAe,GAAGC,IAAI,aAAa,OAAO,MAAM,EAAE,YAAW,IAAK,GAAG,IAAI,MAAMD,EAAE,OAAOC,CAAC,GAAG,IAAI,SAAS,cAAc,QAAQ;AACtJ,QAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;AAChC,YAAMC,IAAI,EAAE,WAAW,IAAI;AAC3B,UAAI,CAACA;AACH,cAAM,IAAI,MAAM,oBAAoB;AACtC,aAAOA,EAAE,aAAa,GAAG,GAAG,CAAC,GAAG,IAAI,QAAQ,CAACC,GAAGC,MAAM;AACpD,UAAE;AAAA,UACA,CAACC,MAAM;AACL,YAAAA,IAAIF,EAAEE,CAAC,IAAID,EAAE,IAAI,MAAM,wBAAwB,CAAC;AAAA,UAClD;AAAA,WACC,KAAK,OAAO,SAAS,EAAE,iBAAiB;AAAA,QACnD;AAAA,MACM,CAAC;AAAA,IACH,SAASJ,GAAG;AACV,YAAM,IAAI,MAAM,eAAeA,KAAK,OAAO,SAASA,EAAE,YAAY,MAAM,EAAE;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM,YAAY,GAAG;AACnB,WAAO;AAAA,MACL,QAAQ;AAAA,IACd;AAAA,EACE;AACF;AACK,MAACM,IAAI,IAAIP,EAAC;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class l {
|
|
2
|
+
/**
|
|
3
|
+
* HEIC 格式浏览器均不原生支持,始终需要解码
|
|
4
|
+
*/
|
|
5
|
+
async needsDecode(a) {
|
|
6
|
+
return a === "image/heic" || a === "image/heif";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 解码 HEIC 文件为 JPEG Blob
|
|
10
|
+
*/
|
|
11
|
+
async decode(a, r) {
|
|
12
|
+
var n, o;
|
|
13
|
+
try {
|
|
14
|
+
const e = await import("heic2any"), i = a instanceof Blob ? a : new Blob([a], { type: "image/heic" }), t = await e.default({
|
|
15
|
+
blob: i,
|
|
16
|
+
toType: (r == null ? void 0 : r.outputFormat) || "image/jpeg",
|
|
17
|
+
quality: 0.9
|
|
18
|
+
});
|
|
19
|
+
return Array.isArray(t) ? t[0] : t;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
throw (n = e == null ? void 0 : e.message) != null && n.includes("DRM") || (o = e == null ? void 0 : e.message) != null && o.includes("protected") ? new Error("HEIC 解码失败,文件受 DRM 保护") : new Error(`HEIC 解码失败,文件可能损坏: ${(e == null ? void 0 : e.message) || "未知错误"}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 获取 HEIC 元数据(当前版本暂不实现,返回空对象)
|
|
26
|
+
*/
|
|
27
|
+
async getMetadata(a) {
|
|
28
|
+
return {
|
|
29
|
+
format: "heic"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const c = new l();
|
|
34
|
+
export {
|
|
35
|
+
c as default
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=heicLoader-CH_raQNn-1fBLaICM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heicLoader-CH_raQNn-1fBLaICM.mjs","sources":["../../../file-preview-core/lib/heicLoader-CH_raQNn.js"],"sourcesContent":["class r {\n /**\n * HEIC 格式浏览器均不原生支持,始终需要解码\n */\n async needsDecode(a) {\n return a === \"image/heic\" || a === \"image/heif\";\n }\n /**\n * 解码 HEIC 文件为 JPEG Blob\n */\n async decode(a, t) {\n var s, n;\n try {\n const e = await import(\"heic2any\"), i = a instanceof Blob ? a : new Blob([a], { type: \"image/heic\" }), c = await e.default({\n blob: i,\n toType: (t == null ? void 0 : t.outputFormat) || \"image/jpeg\",\n quality: 0.9\n });\n return Array.isArray(c) ? c[0] : c;\n } catch (e) {\n throw (s = e == null ? void 0 : e.message) != null && s.includes(\"DRM\") || (n = e == null ? void 0 : e.message) != null && n.includes(\"protected\") ? new Error(\"HEIC 解码失败,文件受 DRM 保护\") : new Error(`HEIC 解码失败,文件可能损坏: ${(e == null ? void 0 : e.message) || \"未知错误\"}`);\n }\n }\n /**\n * 获取 HEIC 元数据(当前版本暂不实现,返回空对象)\n */\n async getMetadata(a) {\n return {\n format: \"heic\"\n };\n }\n}\nconst u = new r();\nexport {\n u as default\n};\n//# sourceMappingURL=heicLoader-CH_raQNn.js.map\n"],"names":["r","t","s","n","c","u"],"mappings":"AAAA,MAAMA,EAAE;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM,YAAY,GAAG;AACnB,WAAO,MAAM,gBAAgB,MAAM;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM,OAAO,GAAGC,GAAG;AACjB,QAAIC,GAAGC;AACP,QAAI;AACF,YAAM,IAAI,MAAM,OAAO,UAAU,GAAG,IAAI,aAAa,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,aAAY,CAAE,GAAGC,IAAI,MAAM,EAAE,QAAQ;AAAA,QACzH,MAAM;AAAA,QACN,SAASH,KAAK,OAAO,SAASA,EAAE,iBAAiB;AAAA,QACjD,SAAS;AAAA,MACjB,CAAO;AACD,aAAO,MAAM,QAAQG,CAAC,IAAIA,EAAE,CAAC,IAAIA;AAAA,IACnC,SAAS,GAAG;AACV,aAAOF,IAAI,KAAK,OAAO,SAAS,EAAE,YAAY,QAAQA,EAAE,SAAS,KAAK,MAAMC,IAAI,KAAK,OAAO,SAAS,EAAE,YAAY,QAAQA,EAAE,SAAS,WAAW,IAAI,IAAI,MAAM,sBAAsB,IAAI,IAAI,MAAM,sBAAsB,KAAK,OAAO,SAAS,EAAE,YAAY,MAAM,EAAE;AAAA,IACtQ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM,YAAY,GAAG;AACnB,WAAO;AAAA,MACL,QAAQ;AAAA,IACd;AAAA,EACE;AACF;AACK,MAACE,IAAI,IAAIL,EAAC;"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { useState as f, useEffect as u } from "react";
|
|
3
|
+
import { u as h, a as g, E as w } from "./index-CuAALtwC.mjs";
|
|
4
|
+
import { u as b } from "./useShikiHighlight-ClbUXJ2p.mjs";
|
|
5
|
+
import { R as y } from "./RendererError-BH6fzLrN.mjs";
|
|
6
|
+
const N = (r) => {
|
|
7
|
+
try {
|
|
8
|
+
const n = new DOMParser().parseFromString(r, "application/xml");
|
|
9
|
+
if (n.querySelector("parsererror")) return r;
|
|
10
|
+
const e = new XMLSerializer().serializeToString(n);
|
|
11
|
+
return x(e);
|
|
12
|
+
} catch {
|
|
13
|
+
return r;
|
|
14
|
+
}
|
|
15
|
+
}, x = (r) => {
|
|
16
|
+
const l = " ", n = /(>)(<)(\/*)/g;
|
|
17
|
+
let s = r.replace(n, `$1
|
|
18
|
+
$2$3`), t = 0;
|
|
19
|
+
return s.split(`
|
|
20
|
+
`).map((e) => {
|
|
21
|
+
let a = 0;
|
|
22
|
+
/^<\/\w/.test(e) ? t = Math.max(t - 1, 0) : /^<\w[^>]*[^/]>.*$/.test(e) && !/<.+<\/.+>$/.test(e) && (a = 1);
|
|
23
|
+
const i = l.repeat(t) + e;
|
|
24
|
+
return t += a, i;
|
|
25
|
+
}).join(`
|
|
26
|
+
`);
|
|
27
|
+
}, X = ({ url: r }) => {
|
|
28
|
+
const l = h(), n = g(), [s, t] = f(""), [e, a] = f(!0), [i, c] = f(null), { html: d } = b(s, "xml");
|
|
29
|
+
return u(() => {
|
|
30
|
+
const m = new AbortController();
|
|
31
|
+
return (async () => {
|
|
32
|
+
try {
|
|
33
|
+
a(!0), c(null);
|
|
34
|
+
const p = await w(r, { fetcher: n, signal: m.signal });
|
|
35
|
+
t(N(p));
|
|
36
|
+
} catch (p) {
|
|
37
|
+
if (p.name === "AbortError") return;
|
|
38
|
+
console.error(p), c(l("xml.load_failed"));
|
|
39
|
+
} finally {
|
|
40
|
+
a(!1);
|
|
41
|
+
}
|
|
42
|
+
})(), () => m.abort();
|
|
43
|
+
}, [r]), e ? /* @__PURE__ */ o("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ o("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" }) }) : i ? /* @__PURE__ */ o(y, { message: i }) : /* @__PURE__ */ o("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg", children: d ? /* @__PURE__ */ o(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
className: "rfp-shiki-wrapper with-line-numbers",
|
|
47
|
+
dangerouslySetInnerHTML: { __html: d }
|
|
48
|
+
}
|
|
49
|
+
) : /* @__PURE__ */ o("pre", { className: "rfp-p-6 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words", children: s }) });
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
X as XmlRenderer
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=index-B57rEPin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B57rEPin.mjs","sources":["../../src/renderers/Xml/index.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useShikiHighlight } from '../../hooks/useShikiHighlight';\nimport { RendererError } from '../RendererError';\n\ninterface XmlRendererProps {\n url: string;\n fileName: string;\n}\n\n/**\n * 用 DOMParser 美化 XML:失败则原样返回\n */\nconst prettyPrintXml = (xml: string): string => {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, 'application/xml');\n // 检测解析错误\n const errNode = doc.querySelector('parsererror');\n if (errNode) return xml;\n // 使用 XSLT 或手动缩进:这里手动缩进更稳\n const serializer = new XMLSerializer();\n const serialized = serializer.serializeToString(doc);\n return indentXml(serialized);\n } catch {\n return xml;\n }\n};\n\nconst indentXml = (xml: string): string => {\n const PADDING = ' ';\n const reg = /(>)(<)(\\/*)/g;\n let formatted = xml.replace(reg, '$1\\n$2$3');\n // 自闭合和 CDATA 等不处理\n let pad = 0;\n return formatted\n .split('\\n')\n .map((line) => {\n let indent = 0;\n if (/^<\\/\\w/.test(line)) {\n pad = Math.max(pad - 1, 0);\n } else if (/^<\\w[^>]*[^/]>.*$/.test(line) && !/<.+<\\/.+>$/.test(line)) {\n indent = 1;\n }\n const padded = PADDING.repeat(pad) + line;\n pad += indent;\n return padded;\n })\n .join('\\n');\n};\n\nexport const XmlRenderer: React.FC<XmlRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const { html: highlighted } = useShikiHighlight(content, 'xml');\n\n useEffect(() => {\n const controller = new AbortController();\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n const raw = await fetchTextUtf8(url, { fetcher, signal: controller.signal });\n setContent(prettyPrintXml(raw));\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n console.error(err);\n setError(t('xml.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n return () => controller.abort();\n }, [url]);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n </div>\n );\n }\n\n if (error) {\n return <RendererError message={error} />;\n }\n\n return (\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg\">\n {highlighted ? (\n <div\n className=\"rfp-shiki-wrapper with-line-numbers\"\n dangerouslySetInnerHTML={{ __html: highlighted }}\n />\n ) : (\n <pre className=\"rfp-p-6 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words\">\n {content}\n </pre>\n )}\n </div>\n );\n};\n"],"names":["prettyPrintXml","xml","doc","serialized","indentXml","PADDING","reg","formatted","pad","line","indent","padded","XmlRenderer","url","t","useTranslator","fetcher","useFetcher","content","setContent","useState","loading","setLoading","error","setError","highlighted","useShikiHighlight","useEffect","controller","raw","fetchTextUtf8","err","jsx","RendererError"],"mappings":";;;;;AAeA,MAAMA,IAAiB,CAACC,MAAwB;AAC9C,MAAI;AAEF,UAAMC,IADS,IAAI,UAAA,EACA,gBAAgBD,GAAK,iBAAiB;AAGzD,QADgBC,EAAI,cAAc,aAAa,EAClC,QAAOD;AAGpB,UAAME,IADa,IAAI,cAAA,EACO,kBAAkBD,CAAG;AACnD,WAAOE,EAAUD,CAAU;AAAA,EAC7B,QAAQ;AACN,WAAOF;AAAA,EACT;AACF,GAEMG,IAAY,CAACH,MAAwB;AACzC,QAAMI,IAAU,MACVC,IAAM;AACZ,MAAIC,IAAYN,EAAI,QAAQK,GAAK;AAAA,KAAU,GAEvCE,IAAM;AACV,SAAOD,EACJ,MAAM;AAAA,CAAI,EACV,IAAI,CAACE,MAAS;AACb,QAAIC,IAAS;AACb,IAAI,SAAS,KAAKD,CAAI,IACpBD,IAAM,KAAK,IAAIA,IAAM,GAAG,CAAC,IAChB,oBAAoB,KAAKC,CAAI,KAAK,CAAC,aAAa,KAAKA,CAAI,MAClEC,IAAS;AAEX,UAAMC,IAASN,EAAQ,OAAOG,CAAG,IAAIC;AACrC,WAAAD,KAAOE,GACAC;AAAA,EACT,CAAC,EACA,KAAK;AAAA,CAAI;AACd,GAEaC,IAA0C,CAAC,EAAE,KAAAC,QAAU;AAClE,QAAMC,IAAIC,EAAA,GACJC,IAAUC,EAAA,GACV,CAACC,GAASC,CAAU,IAAIC,EAAiB,EAAE,GAC3C,CAACC,GAASC,CAAU,IAAIF,EAAS,EAAI,GACrC,CAACG,GAAOC,CAAQ,IAAIJ,EAAwB,IAAI,GAChD,EAAE,MAAMK,EAAA,IAAgBC,EAAkBR,GAAS,KAAK;AAsB9D,SApBAS,EAAU,MAAM;AACd,UAAMC,IAAa,IAAI,gBAAA;AAevB,YAda,YAAY;AACvB,UAAI;AACF,QAAAN,EAAW,EAAI,GACfE,EAAS,IAAI;AACb,cAAMK,IAAM,MAAMC,EAAcjB,GAAK,EAAE,SAAAG,GAAS,QAAQY,EAAW,QAAQ;AAC3E,QAAAT,EAAWnB,EAAe6B,CAAG,CAAC;AAAA,MAChC,SAASE,GAAU;AACjB,YAAIA,EAAI,SAAS,aAAc;AAC/B,gBAAQ,MAAMA,CAAG,GACjBP,EAASV,EAAE,iBAAiB,CAAC;AAAA,MAC/B,UAAA;AACE,QAAAQ,EAAW,EAAK;AAAA,MAClB;AAAA,IACF,GACA,GACO,MAAMM,EAAW,MAAA;AAAA,EAC1B,GAAG,CAACf,CAAG,CAAC,GAEJQ,IAEA,gBAAAW,EAAC,SAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,qHAAoH,EAAA,CACrI,IAIAT,IACK,gBAAAS,EAACC,GAAA,EAAc,SAASV,EAAA,CAAO,IAItC,gBAAAS,EAAC,OAAA,EAAI,WAAU,0DACZ,UAAAP,IACC,gBAAAO;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,yBAAyB,EAAE,QAAQP,EAAA;AAAA,IAAY;AAAA,EAAA,IAGjD,gBAAAO,EAAC,OAAA,EAAI,WAAU,iGACZ,aACH,GAEJ;AAEJ;"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { jsxs as v, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { useState as c, useRef as w, useEffect as P, useCallback as $ } from "react";
|
|
3
|
+
import { motion as me } from "framer-motion";
|
|
4
|
+
import { Loader2 as be } from "lucide-react";
|
|
5
|
+
import { u as ge, G as he, q as xe } from "./index-CuAALtwC.mjs";
|
|
6
|
+
import { R as se } from "./RendererError-BH6fzLrN.mjs";
|
|
7
|
+
const Ue = ({
|
|
8
|
+
url: B,
|
|
9
|
+
zoom: K,
|
|
10
|
+
rotation: ae,
|
|
11
|
+
resetKey: Q,
|
|
12
|
+
fileSize: b,
|
|
13
|
+
file: R,
|
|
14
|
+
onZoomChange: d,
|
|
15
|
+
onNaturalWidthChange: T,
|
|
16
|
+
onNaturalHeightChange: F
|
|
17
|
+
}) => {
|
|
18
|
+
const A = ge(), [N, q] = c(!1), [g, J] = c(null), [O, u] = c(!1), [V, z] = c(0), [L, G] = c(null), [C, h] = c(""), [M, S] = c(1), [U, Z] = c(1), [j, k] = c({ x: 0, y: 0 }), [I, ee] = c(!1), [W, ce] = c({ x: 0, y: 0 }), [_, Y] = c(1), [p, oe] = c({ width: 0, height: 0 }), fe = w(null), H = w(null), x = w(null), D = w(null), E = w(null), o = w(/* @__PURE__ */ new Map());
|
|
19
|
+
P(() => {
|
|
20
|
+
let e = !1;
|
|
21
|
+
return (async () => {
|
|
22
|
+
if (h(""), q(!1), J(null), u(!1), G(null), z(0), k({ x: 0, y: 0 }), Y(1), S(1), Z(1), x.current && (URL.revokeObjectURL(x.current), x.current = null), o.current.forEach((r) => URL.revokeObjectURL(r)), o.current.clear(), D.current = null, E.current = null, !R) {
|
|
23
|
+
e || h(B);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const r = await he(R), t = await xe(r);
|
|
28
|
+
if (!t || !await t.needsDecode(r)) {
|
|
29
|
+
e || h(B);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
u(!0);
|
|
33
|
+
let n;
|
|
34
|
+
if (R instanceof Blob)
|
|
35
|
+
n = R;
|
|
36
|
+
else {
|
|
37
|
+
const a = await fetch(B);
|
|
38
|
+
if (!a.ok) throw new Error("Failed to fetch file");
|
|
39
|
+
n = await a.blob();
|
|
40
|
+
}
|
|
41
|
+
if (e) return;
|
|
42
|
+
if (D.current = n, E.current = t, D.current = n, E.current = t, t.getMetadata)
|
|
43
|
+
try {
|
|
44
|
+
const a = await t.getMetadata(n);
|
|
45
|
+
!e && a.pageCount && a.pageCount > 1 && Z(a.pageCount);
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
const f = await t.decode(n, {
|
|
49
|
+
page: 1,
|
|
50
|
+
fullQuality: !1,
|
|
51
|
+
onProgress: (a) => {
|
|
52
|
+
e || z(a);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
if (e) return;
|
|
56
|
+
const m = typeof f == "string" ? f : URL.createObjectURL(f);
|
|
57
|
+
x.current = m, o.current.set(1, m), h(m), u(!1);
|
|
58
|
+
} catch (r) {
|
|
59
|
+
e || (G((r == null ? void 0 : r.message) || "解码失败"), u(!1));
|
|
60
|
+
}
|
|
61
|
+
})(), () => {
|
|
62
|
+
e = !0;
|
|
63
|
+
};
|
|
64
|
+
}, [B, R]);
|
|
65
|
+
const re = $(async (e) => {
|
|
66
|
+
if (!D.current || !E.current || e < 1 || e > U) return;
|
|
67
|
+
const s = o.current.get(e);
|
|
68
|
+
if (s) {
|
|
69
|
+
S(e), h(s);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
u(!0);
|
|
73
|
+
try {
|
|
74
|
+
const r = await E.current.decode(D.current, { page: e }), t = typeof r == "string" ? r : URL.createObjectURL(r);
|
|
75
|
+
if (o.current.size >= 10) {
|
|
76
|
+
const n = o.current.keys().next().value;
|
|
77
|
+
if (n !== void 0) {
|
|
78
|
+
const f = o.current.get(n);
|
|
79
|
+
f && URL.revokeObjectURL(f), o.current.delete(n);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
o.current.set(e, t), S(e), h(t), u(!1);
|
|
83
|
+
} catch (r) {
|
|
84
|
+
G((r == null ? void 0 : r.message) || "翻页解码失败"), u(!1);
|
|
85
|
+
}
|
|
86
|
+
}, [U]);
|
|
87
|
+
P(() => () => {
|
|
88
|
+
x.current && URL.revokeObjectURL(x.current), o.current.forEach((e) => URL.revokeObjectURL(e)), o.current.clear();
|
|
89
|
+
}, []), P(() => {
|
|
90
|
+
Y(K);
|
|
91
|
+
}, [K]), P(() => {
|
|
92
|
+
Q !== void 0 && k({ x: 0, y: 0 });
|
|
93
|
+
}, [Q]);
|
|
94
|
+
const ie = (e) => {
|
|
95
|
+
q(!0);
|
|
96
|
+
const s = e.currentTarget;
|
|
97
|
+
oe({ width: s.naturalWidth, height: s.naturalHeight }), T == null || T(s.naturalWidth), F == null || F(s.naturalHeight);
|
|
98
|
+
}, X = $((e, s) => {
|
|
99
|
+
const r = H.current;
|
|
100
|
+
if (!r || p.width === 0) return e;
|
|
101
|
+
const t = r.clientWidth, n = r.clientHeight, f = p.width * s, m = p.height * s, a = Math.min(80, t * 0.15, n * 0.15), l = (t + f) / 2 - a, y = (n + m) / 2 - a;
|
|
102
|
+
return {
|
|
103
|
+
x: l > 0 ? Math.max(-l, Math.min(l, e.x)) : 0,
|
|
104
|
+
y: y > 0 ? Math.max(-y, Math.min(y, e.y)) : 0
|
|
105
|
+
};
|
|
106
|
+
}, [p]), le = () => {
|
|
107
|
+
J(A("image.load_failed")), q(!0);
|
|
108
|
+
}, de = () => {
|
|
109
|
+
k({ x: 0, y: 0 }), Y(1), d == null || d(1);
|
|
110
|
+
};
|
|
111
|
+
P(() => {
|
|
112
|
+
const e = H.current;
|
|
113
|
+
if (!e) return;
|
|
114
|
+
const s = (r) => {
|
|
115
|
+
r.preventDefault(), r.stopPropagation();
|
|
116
|
+
const t = e.getBoundingClientRect(), n = r.clientX - t.left - t.width / 2, f = r.clientY - t.top - t.height / 2, m = r.deltaY > 0 ? -0.05 : 0.05;
|
|
117
|
+
Y((a) => {
|
|
118
|
+
const l = Math.max(0.01, Math.min(10, a + m)), y = l / a;
|
|
119
|
+
return k((ne) => X({
|
|
120
|
+
x: n - y * (n - ne.x),
|
|
121
|
+
y: f - y * (f - ne.y)
|
|
122
|
+
}, l)), d == null || d(l), l;
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
return e.addEventListener("wheel", s, { passive: !1 }), () => e.removeEventListener("wheel", s);
|
|
126
|
+
}, [d, X]);
|
|
127
|
+
const ue = $((e) => {
|
|
128
|
+
e.button === 0 && (ee(!0), ce({
|
|
129
|
+
x: e.clientX - j.x,
|
|
130
|
+
y: e.clientY - j.y
|
|
131
|
+
}));
|
|
132
|
+
}, [j]), pe = $((e) => {
|
|
133
|
+
I && k(X({
|
|
134
|
+
x: e.clientX - W.x,
|
|
135
|
+
y: e.clientY - W.y
|
|
136
|
+
}, _));
|
|
137
|
+
}, [I, W, _, X]), te = $(() => {
|
|
138
|
+
ee(!1);
|
|
139
|
+
}, []);
|
|
140
|
+
return /* @__PURE__ */ v(
|
|
141
|
+
"div",
|
|
142
|
+
{
|
|
143
|
+
ref: H,
|
|
144
|
+
className: "rfp-relative rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-overflow-hidden",
|
|
145
|
+
onMouseDown: ue,
|
|
146
|
+
onMouseMove: pe,
|
|
147
|
+
onMouseUp: te,
|
|
148
|
+
onMouseLeave: te,
|
|
149
|
+
style: { cursor: I ? "grabbing" : "grab" },
|
|
150
|
+
children: [
|
|
151
|
+
O && /* @__PURE__ */ v("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", children: [
|
|
152
|
+
/* @__PURE__ */ i(be, { className: "rfp-w-12 rfp-h-12 rfp-text-fg-primary rfp-animate-spin" }),
|
|
153
|
+
/* @__PURE__ */ v("p", { className: "rfp-mt-4 rfp-text-fg-secondary", children: [
|
|
154
|
+
"正在解码... ",
|
|
155
|
+
V > 0 && `${Math.round(V)}%`
|
|
156
|
+
] })
|
|
157
|
+
] }),
|
|
158
|
+
L && /* @__PURE__ */ i("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-1/80 rfp-z-10", children: /* @__PURE__ */ i(se, { message: A("image.decode_failed"), detail: L }) }),
|
|
159
|
+
!N && !g && !O && !L && /* @__PURE__ */ i("div", { className: "rfp-flex rfp-items-center rfp-justify-center", children: /* @__PURE__ */ i("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" }) }),
|
|
160
|
+
g && /* @__PURE__ */ i(se, { message: g }),
|
|
161
|
+
C && /* @__PURE__ */ i(
|
|
162
|
+
me.img,
|
|
163
|
+
{
|
|
164
|
+
ref: fe,
|
|
165
|
+
src: C,
|
|
166
|
+
alt: "Preview",
|
|
167
|
+
className: `rfp-max-w-none rfp-select-none ${!N || g || L ? "rfp-hidden" : ""}`,
|
|
168
|
+
style: {
|
|
169
|
+
transform: `translate(${j.x}px, ${j.y}px) scale(${_}) rotate(${ae}deg)`,
|
|
170
|
+
transformOrigin: "center",
|
|
171
|
+
transition: I ? "none" : "transform 0.3s ease-out"
|
|
172
|
+
},
|
|
173
|
+
onLoad: ie,
|
|
174
|
+
onError: le,
|
|
175
|
+
onDoubleClick: de,
|
|
176
|
+
initial: { opacity: 0 },
|
|
177
|
+
animate: { opacity: N && !g && !L ? 1 : 0 },
|
|
178
|
+
transition: { duration: 0.3 },
|
|
179
|
+
draggable: !1
|
|
180
|
+
}
|
|
181
|
+
),
|
|
182
|
+
N && !g && p.width > 0 && /* @__PURE__ */ v("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", children: [
|
|
183
|
+
p.width,
|
|
184
|
+
" × ",
|
|
185
|
+
p.height,
|
|
186
|
+
b != null && ` · ${b < 1024 ? `${b} B` : b < 1024 * 1024 ? `${(b / 1024).toFixed(1)} KB` : `${(b / (1024 * 1024)).toFixed(1)} MB`}`
|
|
187
|
+
] }),
|
|
188
|
+
U > 1 && /* @__PURE__ */ v("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", children: [
|
|
189
|
+
/* @__PURE__ */ i(
|
|
190
|
+
"button",
|
|
191
|
+
{
|
|
192
|
+
type: "button",
|
|
193
|
+
onClick: () => re(M - 1),
|
|
194
|
+
disabled: M <= 1 || O,
|
|
195
|
+
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",
|
|
196
|
+
children: "上一页"
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
/* @__PURE__ */ v("span", { className: "rfp-text-fg-secondary rfp-tabular-nums", children: [
|
|
200
|
+
M,
|
|
201
|
+
" / ",
|
|
202
|
+
U
|
|
203
|
+
] }),
|
|
204
|
+
/* @__PURE__ */ i(
|
|
205
|
+
"button",
|
|
206
|
+
{
|
|
207
|
+
type: "button",
|
|
208
|
+
onClick: () => re(M + 1),
|
|
209
|
+
disabled: M >= U || O,
|
|
210
|
+
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",
|
|
211
|
+
children: "下一页"
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
] })
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
export {
|
|
220
|
+
Ue as ImageRenderer
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=index-BCuRRLYt.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BCuRRLYt.mjs","sources":["../../src/renderers/Image/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { motion } from 'framer-motion';\nimport { Loader2 } from 'lucide-react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { detectImageFormat, getLoaderForMimeType } from '@eternalheart/file-preview-core';\nimport type { PreviewFile } from '@eternalheart/file-preview-core';\nimport { RendererError } from '../RendererError';\n\ninterface ImageRendererProps {\n url: string;\n zoom: number;\n rotation: number;\n resetKey?: number;\n fileSize?: number;\n file?: PreviewFile | File;\n onZoomChange?: (zoom: number) => void;\n onNaturalWidthChange?: (width: number) => void;\n onNaturalHeightChange?: (height: number) => void;\n}\n\nexport const ImageRenderer: React.FC<ImageRendererProps> = ({\n url,\n zoom,\n rotation,\n resetKey,\n fileSize,\n file,\n onZoomChange,\n onNaturalWidthChange,\n onNaturalHeightChange\n}) => {\n const t = useTranslator();\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 [internalZoom, setInternalZoom] = useState(1);\n const [naturalSize, setNaturalSize] = useState({ width: 0, height: 0 });\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\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 setInternalZoom(1);\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 // 缓存 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 // 调用 loader 解码(第 1 页 / 缩略图模式)\n const decodedBlob = await loader.decode(fileBlob, {\n page: 1,\n fullQuality: false,\n onProgress: (percent: number) => {\n if (!cancelled) {\n setDecodeProgress(percent);\n }\n },\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 // 当外部 zoom 改变时,同步内部 zoom\n useEffect(() => {\n setInternalZoom(zoom);\n }, [zoom]);\n\n // 适应窗口/原始尺寸等操作时重置位置居中\n useEffect(() => {\n if (resetKey !== undefined) {\n setPosition({ x: 0, y: 0 });\n }\n }, [resetKey]);\n\n const handleLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setLoaded(true);\n const img = e.currentTarget;\n setNaturalSize({ width: img.naturalWidth, height: img.naturalHeight });\n onNaturalWidthChange?.(img.naturalWidth);\n onNaturalHeightChange?.(img.naturalHeight);\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 setInternalZoom(1);\n onZoomChange?.(1);\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 setInternalZoom(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 onZoomChange?.(newZoom);\n return newZoom;\n });\n };\n\n container.addEventListener('wheel', handleWheelNative, { passive: false });\n return () => container.removeEventListener('wheel', handleWheelNative);\n }, [onZoomChange, clampPosition]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (e.button !== 0) return;\n setIsDragging(true);\n setDragStart({\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n });\n }, [position]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!isDragging) return;\n setPosition(clampPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n }, internalZoom));\n }, [isDragging, dragStart, internalZoom, clampPosition]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n }, []);\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' }}\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(${internalZoom}) rotate(${rotation}deg)`,\n transformOrigin: 'center',\n transition: isDragging ? 'none' : 'transform 0.3s ease-out',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onDoubleClick={handleDoubleClick}\n initial={{ opacity: 0 }}\n animate={{ opacity: loaded && !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":["ImageRenderer","url","zoom","rotation","resetKey","fileSize","file","onZoomChange","onNaturalWidthChange","onNaturalHeightChange","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","internalZoom","setInternalZoom","naturalSize","setNaturalSize","imgRef","useRef","containerRef","blobUrlRef","fileBlobRef","loaderRef","pageCacheRef","useEffect","cancelled","mimeType","detectImageFormat","loader","getLoaderForMimeType","fileBlob","response","metadata","decodedBlob","percent","blobUrl","err","handlePageChange","useCallback","page","cached","firstKey","oldUrl","handleLoad","img","clampPosition","pos","currentZoom","container","containerW","containerH","imgW","imgH","margin","rangeX","rangeY","handleError","handleDoubleClick","handleWheelNative","e","rect","mouseX","mouseY","delta","prev","newZoom","scale","handleMouseDown","handleMouseMove","handleMouseUp","jsxs","jsx","Loader2","RendererError","motion"],"mappings":"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"}
|