@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
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { jsx as r, jsxs as A } from "react/jsx-runtime";
|
|
2
|
-
import { useState as f, useRef as G, useEffect as w, useCallback as P } from "react";
|
|
3
|
-
import T from "mammoth";
|
|
4
|
-
import { u as D, a as I } from "./index-Bv93wiEK.mjs";
|
|
5
|
-
const H = 1123, b = 60, _ = 50, S = H - b * 2, j = 24, E = {
|
|
6
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
7
|
-
lineHeight: "1.8",
|
|
8
|
-
color: "#333"
|
|
9
|
-
}, M = ({ url: i }) => {
|
|
10
|
-
const c = D(), p = I(), [n, u] = f(""), [N, d] = f(!0), [h, m] = f(null), [x, g] = f([]), a = G(null);
|
|
11
|
-
w(() => {
|
|
12
|
-
(async () => {
|
|
13
|
-
d(!0), m(null), u("");
|
|
14
|
-
try {
|
|
15
|
-
const e = await p(i);
|
|
16
|
-
if (!e.ok)
|
|
17
|
-
throw new Error("文件加载失败");
|
|
18
|
-
const t = await e.arrayBuffer(), s = await T.convertToHtml({ arrayBuffer: t });
|
|
19
|
-
u(s.value);
|
|
20
|
-
} catch (e) {
|
|
21
|
-
console.error("Docx 解析错误:", e), m(c("docx.parse_failed"));
|
|
22
|
-
} finally {
|
|
23
|
-
d(!1);
|
|
24
|
-
}
|
|
25
|
-
})();
|
|
26
|
-
}, [i, p, c]);
|
|
27
|
-
const y = P(() => {
|
|
28
|
-
const o = a.current;
|
|
29
|
-
if (!o || !n) return;
|
|
30
|
-
const e = Array.from(o.children);
|
|
31
|
-
if (e.length === 0) {
|
|
32
|
-
g([n]);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const t = [[]];
|
|
36
|
-
let s = 0;
|
|
37
|
-
for (const l of e) {
|
|
38
|
-
const v = l.offsetHeight;
|
|
39
|
-
s > 0 && s + v > S && (t.push([]), s = 0), t[t.length - 1].push(l.outerHTML), s += v;
|
|
40
|
-
}
|
|
41
|
-
t.length === 0 && t.push([]), g(t.map((l) => l.join("")));
|
|
42
|
-
}, [n]);
|
|
43
|
-
return w(() => {
|
|
44
|
-
!n || !a.current || requestAnimationFrame(() => {
|
|
45
|
-
y();
|
|
46
|
-
});
|
|
47
|
-
}, [n, y]), N ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("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" }) }) : h ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ r("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ r("p", { className: "rfp-text-lg", children: h }) }) }) : /* @__PURE__ */ A(
|
|
48
|
-
"div",
|
|
49
|
-
{
|
|
50
|
-
className: "rfp-w-full rfp-h-full rfp-overflow-auto",
|
|
51
|
-
style: { background: "rgba(0, 0, 0, 0.15)" },
|
|
52
|
-
children: [
|
|
53
|
-
/* @__PURE__ */ r(
|
|
54
|
-
"div",
|
|
55
|
-
{
|
|
56
|
-
ref: a,
|
|
57
|
-
dangerouslySetInnerHTML: { __html: n },
|
|
58
|
-
style: {
|
|
59
|
-
...E,
|
|
60
|
-
position: "absolute",
|
|
61
|
-
visibility: "hidden",
|
|
62
|
-
width: `${794 - _ * 2}px`,
|
|
63
|
-
pointerEvents: "none"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
),
|
|
67
|
-
/* @__PURE__ */ r(
|
|
68
|
-
"div",
|
|
69
|
-
{
|
|
70
|
-
className: "rfp-py-6 md:rfp-py-10 rfp-flex rfp-flex-col rfp-items-center",
|
|
71
|
-
style: { gap: `${j}px` },
|
|
72
|
-
children: (x.length > 0 ? x : [""]).map((o, e) => /* @__PURE__ */ r(
|
|
73
|
-
"div",
|
|
74
|
-
{
|
|
75
|
-
style: {
|
|
76
|
-
width: "100%",
|
|
77
|
-
maxWidth: "794px",
|
|
78
|
-
minHeight: `${H}px`,
|
|
79
|
-
background: "white",
|
|
80
|
-
boxShadow: "0 2px 12px rgba(0, 0, 0, 0.15)",
|
|
81
|
-
flexShrink: 0,
|
|
82
|
-
padding: `${b}px ${_}px`
|
|
83
|
-
},
|
|
84
|
-
children: /* @__PURE__ */ r(
|
|
85
|
-
"div",
|
|
86
|
-
{
|
|
87
|
-
dangerouslySetInnerHTML: { __html: o },
|
|
88
|
-
style: E
|
|
89
|
-
}
|
|
90
|
-
)
|
|
91
|
-
},
|
|
92
|
-
e
|
|
93
|
-
))
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
};
|
|
100
|
-
export {
|
|
101
|
-
M as DocxRenderer
|
|
102
|
-
};
|
|
103
|
-
//# sourceMappingURL=index-BNUiNUWa.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BNUiNUWa.mjs","sources":["../../src/renderers/Docx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport mammoth from 'mammoth';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface DocxRendererProps {\n url: string;\n}\n\n// A4 page dimensions (96dpi)\nconst PAGE_HEIGHT = 1123;\nconst PAGE_PADDING_Y = 60;\nconst PAGE_PADDING_X = 50;\nconst PAGE_CONTENT_HEIGHT = PAGE_HEIGHT - PAGE_PADDING_Y * 2;\nconst PAGE_GAP = 24;\n\nconst contentStyle: React.CSSProperties = {\n fontFamily: 'system-ui, -apple-system, sans-serif',\n lineHeight: '1.8',\n color: '#333',\n};\n\nexport const DocxRenderer: React.FC<DocxRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [html, setHtml] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [pages, setPages] = useState<string[]>([]);\n const measureRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const loadDocx = async () => {\n setLoading(true);\n setError(null);\n setHtml('');\n\n try {\n const response = await fetcher(url);\n if (!response.ok) {\n throw new Error('文件加载失败');\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const result = await mammoth.convertToHtml({ arrayBuffer });\n setHtml(result.value);\n } catch (err) {\n console.error('Docx 解析错误:', err);\n setError(t('docx.parse_failed'));\n } finally {\n setLoading(false);\n }\n };\n\n loadDocx();\n }, [url, fetcher, t]);\n\n const paginate = useCallback(() => {\n const container = measureRef.current;\n if (!container || !html) return;\n\n const children = Array.from(container.children) as HTMLElement[];\n if (children.length === 0) {\n setPages([html]);\n return;\n }\n\n const result: string[][] = [[]];\n let currentPageUsed = 0;\n\n for (const child of children) {\n const h = child.offsetHeight;\n\n // If adding this block would exceed page content area and page isn't empty,\n // start a new page\n if (currentPageUsed > 0 && currentPageUsed + h > PAGE_CONTENT_HEIGHT) {\n result.push([]);\n currentPageUsed = 0;\n }\n\n result[result.length - 1].push(child.outerHTML);\n currentPageUsed += h;\n }\n\n // At least one page\n if (result.length === 0) result.push([]);\n\n setPages(result.map(blocks => blocks.join('')));\n }, [html]);\n\n useEffect(() => {\n if (!html || !measureRef.current) return;\n requestAnimationFrame(() => {\n paginate();\n });\n }, [html, paginate]);\n\n 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 (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className=\"rfp-w-full rfp-h-full rfp-overflow-auto\"\n style={{ background: 'rgba(0, 0, 0, 0.15)' }}\n >\n {/* Hidden measurement div — same width as page content area */}\n <div\n ref={measureRef}\n dangerouslySetInnerHTML={{ __html: html }}\n style={{\n ...contentStyle,\n position: 'absolute',\n visibility: 'hidden',\n width: `${794 - PAGE_PADDING_X * 2}px`,\n pointerEvents: 'none',\n }}\n />\n\n {/* Visible pages */}\n <div\n className=\"rfp-py-6 md:rfp-py-10 rfp-flex rfp-flex-col rfp-items-center\"\n style={{ gap: `${PAGE_GAP}px` }}\n >\n {(pages.length > 0 ? pages : ['']).map((pageHtml, i) => (\n <div\n key={i}\n style={{\n width: '100%',\n maxWidth: '794px',\n minHeight: `${PAGE_HEIGHT}px`,\n background: 'white',\n boxShadow: '0 2px 12px rgba(0, 0, 0, 0.15)',\n flexShrink: 0,\n padding: `${PAGE_PADDING_Y}px ${PAGE_PADDING_X}px`,\n }}\n >\n <div\n dangerouslySetInnerHTML={{ __html: pageHtml }}\n style={contentStyle}\n />\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":["PAGE_HEIGHT","PAGE_PADDING_Y","PAGE_PADDING_X","PAGE_CONTENT_HEIGHT","PAGE_GAP","contentStyle","DocxRenderer","url","t","useTranslator","fetcher","useFetcher","html","setHtml","useState","loading","setLoading","error","setError","pages","setPages","measureRef","useRef","useEffect","response","arrayBuffer","result","mammoth","err","paginate","useCallback","container","children","currentPageUsed","child","h","blocks","jsx","jsxs","pageHtml","i"],"mappings":";;;;AAUA,MAAMA,IAAc,MACdC,IAAiB,IACjBC,IAAiB,IACjBC,IAAsBH,IAAcC,IAAiB,GACrDG,IAAW,IAEXC,IAAoC;AAAA,EACxC,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,OAAO;AACT,GAEaC,IAA4C,CAAC,EAAE,KAAAC,QAAU;AACpE,QAAMC,IAAIC,EAAA,GACJC,IAAUC,EAAA,GACV,CAACC,GAAMC,CAAO,IAAIC,EAAiB,EAAE,GACrC,CAACC,GAASC,CAAU,IAAIF,EAAS,EAAI,GACrC,CAACG,GAAOC,CAAQ,IAAIJ,EAAwB,IAAI,GAChD,CAACK,GAAOC,CAAQ,IAAIN,EAAmB,CAAA,CAAE,GACzCO,IAAaC,EAAuB,IAAI;AAE9C,EAAAC,EAAU,MAAM;AAuBd,KAtBiB,YAAY;AAC3B,MAAAP,EAAW,EAAI,GACfE,EAAS,IAAI,GACbL,EAAQ,EAAE;AAEV,UAAI;AACF,cAAMW,IAAW,MAAMd,EAAQH,CAAG;AAClC,YAAI,CAACiB,EAAS;AACZ,gBAAM,IAAI,MAAM,QAAQ;AAG1B,cAAMC,IAAc,MAAMD,EAAS,YAAA,GAC7BE,IAAS,MAAMC,EAAQ,cAAc,EAAE,aAAAF,GAAa;AAC1D,QAAAZ,EAAQa,EAAO,KAAK;AAAA,MACtB,SAASE,GAAK;AACZ,gBAAQ,MAAM,cAAcA,CAAG,GAC/BV,EAASV,EAAE,mBAAmB,CAAC;AAAA,MACjC,UAAA;AACE,QAAAQ,EAAW,EAAK;AAAA,MAClB;AAAA,IACF,GAEA;AAAA,EACF,GAAG,CAACT,GAAKG,GAASF,CAAC,CAAC;AAEpB,QAAMqB,IAAWC,EAAY,MAAM;AACjC,UAAMC,IAAYV,EAAW;AAC7B,QAAI,CAACU,KAAa,CAACnB,EAAM;AAEzB,UAAMoB,IAAW,MAAM,KAAKD,EAAU,QAAQ;AAC9C,QAAIC,EAAS,WAAW,GAAG;AACzB,MAAAZ,EAAS,CAACR,CAAI,CAAC;AACf;AAAA,IACF;AAEA,UAAMc,IAAqB,CAAC,EAAE;AAC9B,QAAIO,IAAkB;AAEtB,eAAWC,KAASF,GAAU;AAC5B,YAAMG,IAAID,EAAM;AAIhB,MAAID,IAAkB,KAAKA,IAAkBE,IAAIhC,MAC/CuB,EAAO,KAAK,EAAE,GACdO,IAAkB,IAGpBP,EAAOA,EAAO,SAAS,CAAC,EAAE,KAAKQ,EAAM,SAAS,GAC9CD,KAAmBE;AAAA,IACrB;AAGA,IAAIT,EAAO,WAAW,KAAGA,EAAO,KAAK,CAAA,CAAE,GAEvCN,EAASM,EAAO,IAAI,CAAAU,MAAUA,EAAO,KAAK,EAAE,CAAC,CAAC;AAAA,EAChD,GAAG,CAACxB,CAAI,CAAC;AAST,SAPAW,EAAU,MAAM;AACd,IAAI,CAACX,KAAQ,CAACS,EAAW,WACzB,sBAAsB,MAAM;AAC1B,MAAAQ,EAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACjB,GAAMiB,CAAQ,CAAC,GAEfd,IAEA,gBAAAsB,EAAC,SAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,qHAAoH,EAAA,CACrI,IAIApB,IAEA,gBAAAoB,EAAC,OAAA,EAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,yCACb,UAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,eAAe,UAAApB,EAAA,CAAM,GACpC,GACF,IAKF,gBAAAqB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,YAAY,sBAAA;AAAA,MAGrB,UAAA;AAAA,QAAA,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKhB;AAAA,YACL,yBAAyB,EAAE,QAAQT,EAAA;AAAA,YACnC,OAAO;AAAA,cACL,GAAGP;AAAA,cACH,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,OAAO,GAAG,MAAMH,IAAiB,CAAC;AAAA,cAClC,eAAe;AAAA,YAAA;AAAA,UACjB;AAAA,QAAA;AAAA,QAIF,gBAAAmC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,KAAK,GAAGjC,CAAQ,KAAA;AAAA,YAEvB,WAAAe,EAAM,SAAS,IAAIA,IAAQ,CAAC,EAAE,GAAG,IAAI,CAACoB,GAAUC,MAChD,gBAAAH;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,OAAO;AAAA,kBACL,OAAO;AAAA,kBACP,UAAU;AAAA,kBACV,WAAW,GAAGrC,CAAW;AAAA,kBACzB,YAAY;AAAA,kBACZ,WAAW;AAAA,kBACX,YAAY;AAAA,kBACZ,SAAS,GAAGC,CAAc,MAAMC,CAAc;AAAA,gBAAA;AAAA,gBAGhD,UAAA,gBAAAmC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,yBAAyB,EAAE,QAAQE,EAAA;AAAA,oBACnC,OAAOlC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACT;AAAA,cAdKmC;AAAA,YAAA,CAgBR;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BSD3w5eG.mjs","sources":["../../src/renderers/Epub/index.tsx"],"sourcesContent":["import { useEffect, useRef, useState, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport ePub from '@likecoin/epub-ts';\nimport { X } from 'lucide-react';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\n// 全局注入 epubjs 容器样式(只注入一次)\nif (typeof document !== 'undefined' && !document.getElementById('rfp-epub-styles')) {\n const styleEl = document.createElement('style');\n styleEl.id = 'rfp-epub-styles';\n styleEl.textContent = `\n .epub-container { overflow-y: auto !important; scrollbar-width: thin; }\n .epub-container::-webkit-scrollbar { width: 8px; }\n .epub-container::-webkit-scrollbar-track { background: transparent; }\n .epub-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }\n .epub-container::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.3); }\n .epub-view > iframe { background: white; }\n `;\n document.head.appendChild(styleEl);\n}\n\nexport interface TocItem {\n label: string;\n href: string;\n subitems?: TocItem[];\n}\n\nexport interface EpubRendererHandle {\n prevPage: () => void;\n nextPage: () => void;\n toggleFullWidth: () => void;\n toggleToc: () => void;\n}\n\ninterface EpubRendererProps {\n url: string;\n onChapterChange?: (current: number, total: number) => void;\n onFullWidthChange?: (isFullWidth: boolean) => void;\n}\n\ninterface RenditionLike {\n display: (target?: string) => Promise<unknown>;\n next: () => Promise<unknown>;\n prev: () => Promise<unknown>;\n on: (event: string, cb: (...args: unknown[]) => void) => void;\n resize: (width: number, height: number) => void;\n currentLocation: () => unknown;\n destroy?: () => void;\n themes: {\n register: (name: string, styles: Record<string, unknown>) => void;\n select: (name: string) => void;\n };\n}\n\ninterface BookLike {\n ready: Promise<unknown>;\n loaded: { navigation: Promise<unknown> };\n locations: {\n generate: (chars: number) => Promise<string[]>;\n length: () => number;\n locationFromCfi: (cfi: string) => number;\n };\n renderTo: (el: HTMLElement, opts: Record<string, unknown>) => RenditionLike;\n destroy: () => void;\n}\n\nconst A4_WIDTH = 794;\n\nexport const EpubRenderer = forwardRef<EpubRendererHandle, EpubRendererProps>(\n ({ url, onChapterChange, onFullWidthChange }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const viewerRef = useRef<HTMLDivElement>(null);\n const bookRef = useRef<BookLike | null>(null);\n const renditionRef = useRef<RenditionLike | null>(null);\n const onChapterChangeRef = useRef(onChapterChange);\n const onFullWidthChangeRef = useRef(onFullWidthChange);\n onChapterChangeRef.current = onChapterChange;\n onFullWidthChangeRef.current = onFullWidthChange;\n\n const totalLocationsRef = useRef(0);\n const lastCfiRef = useRef<string | null>(null);\n const isFullWidthRef = useRef(false);\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [isFullWidth, setIsFullWidth] = useState(false);\n const [toc, setToc] = useState<TocItem[]>([]);\n const [showToc, setShowToc] = useState(false);\n const [activeTocHref, setActiveTocHref] = useState<string>('');\n const tocRef = useRef<TocItem[]>([]);\n tocRef.current = toc;\n\n isFullWidthRef.current = isFullWidth;\n\n const handlePrev = useCallback(() => {\n renditionRef.current?.prev();\n }, []);\n\n const handleNext = useCallback(() => {\n renditionRef.current?.next();\n }, []);\n\n // 滚动监听:接近底部时强制触发 check 加载后续 section\n const scrollContainerRef = useRef<Element | null>(null);\n const scrollRafRef = useRef(0);\n\n const onScrollRef = useRef((_e?: Event) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n const el = container as HTMLElement;\n const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 200;\n if (nearBottom) {\n try {\n const mgr = (renditionRef.current as unknown as { manager?: { check?: (t?: number, e?: number) => Promise<unknown> } })?.manager;\n mgr?.check?.(500, 500);\n } catch { /* ignore */ }\n }\n });\n\n const reattachScrollListener = useCallback(() => {\n // 清理旧监听\n if (scrollContainerRef.current) {\n scrollContainerRef.current.removeEventListener('scroll', onScrollRef.current);\n scrollContainerRef.current = null;\n }\n cancelAnimationFrame(scrollRafRef.current);\n\n const tryAttach = () => {\n const container = viewerRef.current?.querySelector('.epub-container') ?? null;\n if (!container) {\n scrollRafRef.current = requestAnimationFrame(tryAttach);\n return;\n }\n scrollContainerRef.current = container;\n container.addEventListener('scroll', onScrollRef.current, { passive: true });\n };\n scrollRafRef.current = requestAnimationFrame(tryAttach);\n }, []);\n\n const toggleFullWidth = useCallback(() => {\n const newVal = !isFullWidthRef.current;\n setIsFullWidth(newVal);\n onFullWidthChangeRef.current?.(newVal);\n // 等 CSS transition 完成后再 resize 并恢复位置\n setTimeout(() => {\n const viewer = viewerRef.current;\n const rendition = renditionRef.current;\n if (!viewer || !rendition) return;\n rendition.resize(viewer.offsetWidth, viewer.offsetHeight);\n // 重排后恢复阅读位置\n if (lastCfiRef.current) {\n rendition.display(lastCfiRef.current);\n }\n // resize/display 可能重建 .epub-container,需要重新绑定滚动监听\n reattachScrollListener();\n }, 350);\n }, [reattachScrollListener]);\n\n const toggleToc = useCallback(() => {\n setShowToc(prev => !prev);\n }, []);\n\n const handleTocClick = useCallback((href: string) => {\n setActiveTocHref(href);\n renditionRef.current?.display(href);\n setShowToc(false);\n }, []);\n\n useImperativeHandle(ref, () => ({\n prevPage: handlePrev,\n nextPage: handleNext,\n toggleFullWidth,\n toggleToc,\n }), [handlePrev, handleNext, toggleFullWidth, toggleToc]);\n\n useEffect(() => {\n const viewer = viewerRef.current;\n if (!viewer) return;\n\n setLoading(true);\n setError(null);\n setToc([]);\n setShowToc(false);\n viewer.innerHTML = '';\n lastCfiRef.current = null;\n totalLocationsRef.current = 0;\n\n let cancelled = false;\n // StrictMode 下 effect 会立即 mount→unmount→mount\n // 用 microtask 延迟初始化,让第一次的 cleanup 先执行,避免 epubjs 内部状态被污染\n const loadTimer = window.setTimeout(() => {\n if (cancelled) return;\n load();\n }, 0);\n\n const load = async () => {\n try {\n let bookInput: string | ArrayBuffer = url;\n if (url.startsWith('blob:')) {\n const resp = await fetcher(url);\n bookInput = await resp.arrayBuffer();\n }\n\n const book = ePub(bookInput) as unknown as BookLike;\n bookRef.current = book;\n\n const rendition = book.renderTo(viewer, {\n manager: 'continuous',\n flow: 'scrolled',\n width: '100%',\n height: '100%',\n });\n renditionRef.current = rendition;\n\n rendition.themes.register('default', {\n body: {\n background: '#ffffff !important',\n color: '#1a1a1a !important',\n 'font-family': '\"Noto Serif SC\", \"Source Han Serif SC\", Georgia, \"Times New Roman\", serif !important',\n 'font-size': '16px !important',\n 'line-height': '2 !important',\n padding: '40px 60px !important',\n 'max-width': '100% !important',\n 'box-sizing': 'border-box !important',\n 'word-break': 'break-word !important',\n 'overflow-wrap': 'break-word !important',\n },\n p: { 'text-indent': '2em !important', margin: '0.8em 0 !important' },\n h1: { 'text-align': 'center !important', margin: '1.5em 0 1em !important' },\n h2: { margin: '1.2em 0 0.8em !important' },\n h3: { margin: '1em 0 0.6em !important' },\n img: { 'max-width': '100% !important', height: 'auto !important' },\n a: { color: '#2563eb !important', 'text-decoration': 'none !important' },\n });\n rendition.themes.select('default');\n\n await book.ready;\n\n // 异步生成 locations 索引(用于实时页数)\n book.locations.generate(1024).then(() => {\n if (cancelled) return;\n totalLocationsRef.current = book.locations.length();\n // 触发一次更新让父组件拿到 total\n const loc = renditionRef.current?.currentLocation() as { start?: { location?: number; cfi?: string } } | undefined;\n const cur = loc?.start?.location ?? 0;\n onChapterChangeRef.current?.(cur + 1, totalLocationsRef.current);\n }).catch(() => { /* ignore */ });\n\n // 获取目录\n const nav = await book.loaded.navigation as { toc?: TocItem[] };\n if (!cancelled && Array.isArray(nav?.toc)) {\n setToc(nav.toc);\n }\n\n await rendition.display();\n\n if (cancelled) return;\n\n setLoading(false);\n onChapterChangeRef.current?.(1, totalLocationsRef.current || 1);\n\n rendition.on('relocated', (location: unknown) => {\n const loc = location as { start?: { cfi?: string; location?: number; href?: string } };\n if (loc?.start?.cfi) {\n lastCfiRef.current = loc.start.cfi;\n }\n if (loc?.start?.href) {\n // 根据 spine href 查找匹配的 TOC 项\n const spineHref = loc.start.href;\n const matches: string[] = [];\n const collect = (items: TocItem[]) => {\n for (const item of items) {\n const base = item.href.split('#')[0];\n if (base && (spineHref === base || spineHref.endsWith('/' + base) || spineHref.endsWith(base))) {\n matches.push(item.href);\n }\n if (item.subitems) collect(item.subitems);\n }\n };\n collect(tocRef.current);\n if (matches.length === 1) {\n // 唯一匹配,直接设置\n setActiveTocHref(matches[0]);\n }\n // 多个匹配(同一文件不同 anchor)时保持当前选中(由点击设置)\n }\n const cur = loc?.start?.location;\n const total = totalLocationsRef.current;\n if (typeof cur === 'number' && total > 0) {\n onChapterChangeRef.current?.(cur + 1, total);\n }\n });\n\n } catch (err) {\n console.error('EPUB 加载错误:', err);\n if (!cancelled) {\n setError(t('epub.load_failed'));\n setLoading(false);\n }\n }\n };\n\n return () => {\n cancelled = true;\n window.clearTimeout(loadTimer);\n try { renditionRef.current?.destroy?.(); } catch { /* ignore */ }\n try { bookRef.current?.destroy(); } catch { /* ignore */ }\n renditionRef.current = null;\n bookRef.current = null;\n };\n }, [url]);\n\n useEffect(() => {\n const onResize = () => {\n const viewer = viewerRef.current;\n if (!viewer || !renditionRef.current) return;\n renditionRef.current.resize(viewer.offsetWidth, viewer.offsetHeight);\n };\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n\n useEffect(() => {\n reattachScrollListener();\n return () => {\n cancelAnimationFrame(scrollRafRef.current);\n scrollContainerRef.current?.removeEventListener('scroll', onScrollRef.current);\n };\n }, [url, reattachScrollListener]);\n\n const isActive = useCallback((href: string) => {\n return href === activeTocHref;\n }, [activeTocHref]);\n\n const renderTocItems = (items: TocItem[], depth = 0) => (\n <ul style={{ marginLeft: depth > 0 ? 16 : 0 }}>\n {items.map((item, i) => {\n const active = isActive(item.href);\n return (\n <li key={`${item.href}-${i}`}>\n <button\n onClick={() => handleTocClick(item.href)}\n className={`rfp-w-full rfp-text-left rfp-py-2 rfp-px-3 rfp-text-sm rfp-rounded rfp-transition-all rfp-truncate ${active\n ? 'rfp-text-fg-primary rfp-bg-surface-3 rfp-font-medium'\n : 'rfp-text-fg-secondary hover:rfp-text-fg-primary hover:rfp-bg-surface-2'\n }`}\n title={item.label}\n >\n {item.label.trim()}\n </button>\n {item.subitems && item.subitems.length > 0 && renderTocItems(item.subitems, depth + 1)}\n </li>\n );\n })}\n </ul>\n );\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-flex rfp-justify-center rfp-bg-[#f5f5f0] rfp-overflow-hidden\">\n {error && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n )}\n\n {loading && !error && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-z-10\">\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 {toc.length > 0 && (\n <div\n className=\"rfp-absolute rfp-inset-0 rfp-z-20 rfp-flex rfp-transition-opacity rfp-duration-300\"\n style={{\n opacity: showToc ? 1 : 0,\n pointerEvents: showToc ? 'auto' : 'none',\n }}\n >\n <div\n className=\"rfp-w-72 rfp-max-w-[80%] rfp-h-full rfp-bg-surface-overlay rfp-backdrop-blur-xl rfp-border-r rfp-border-line-weak rfp-flex rfp-flex-col rfp-shadow-2xl rfp-transition-transform rfp-duration-300\"\n style={{ transform: showToc ? 'translateX(0)' : 'translateX(-100%)' }}\n >\n <div className=\"rfp-flex rfp-items-center rfp-justify-between rfp-px-4 rfp-py-3 rfp-border-b rfp-border-line-weak rfp-flex-shrink-0\">\n <span className=\"rfp-text-fg-primary rfp-font-medium rfp-text-sm\">{t('toolbar.toc')}</span>\n <button\n onClick={() => setShowToc(false)}\n className=\"rfp-text-fg-tertiary hover:rfp-text-fg-primary rfp-transition-colors\"\n >\n <X className=\"rfp-w-4 rfp-h-4\" />\n </button>\n </div>\n <div className=\"rfp-flex-1 rfp-overflow-y-auto rfp-py-4 rfp-px-1\">\n {renderTocItems(toc)}\n </div>\n </div>\n <div\n className=\"rfp-flex-1 rfp-transition-opacity rfp-duration-300\"\n style={{ background: showToc ? 'rgba(0,0,0,0.3)' : 'transparent' }}\n onClick={() => setShowToc(false)}\n />\n </div>\n )}\n\n {!error && (\n <div\n ref={viewerRef}\n className=\"rfp-h-full rfp-bg-surface-toolbar rfp-shadow-lg\"\n style={{\n width: isFullWidth ? '100%' : `${A4_WIDTH}px`,\n maxWidth: '100%',\n transition: 'width 0.3s ease',\n overflow: 'hidden',\n }}\n />\n )}\n </div>\n );\n }\n);\n"],"names":["styleEl","A4_WIDTH","EpubRenderer","forwardRef","url","onChapterChange","onFullWidthChange","ref","t","useTranslator","fetcher","useFetcher","viewerRef","useRef","bookRef","renditionRef","onChapterChangeRef","onFullWidthChangeRef","totalLocationsRef","lastCfiRef","isFullWidthRef","loading","setLoading","useState","error","setError","isFullWidth","setIsFullWidth","toc","setToc","showToc","setShowToc","activeTocHref","setActiveTocHref","tocRef","handlePrev","useCallback","_a","handleNext","scrollContainerRef","scrollRafRef","onScrollRef","_e","container","el","mgr","_b","reattachScrollListener","tryAttach","toggleFullWidth","newVal","viewer","rendition","toggleToc","prev","handleTocClick","href","useImperativeHandle","useEffect","cancelled","loadTimer","load","bookInput","book","ePub","loc","cur","_c","nav","location","spineHref","matches","collect","items","item","base","total","_d","err","onResize","isActive","renderTocItems","depth","jsx","i","active","jsxs","X"],"mappings":";;;;;AAOA,IAAI,OAAO,WAAa,OAAe,CAAC,SAAS,eAAe,iBAAiB,GAAG;AAClF,QAAMA,IAAU,SAAS,cAAc,OAAO;AAC9C,EAAAA,EAAQ,KAAK,mBACbA,EAAQ,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQtB,SAAS,KAAK,YAAYA,CAAO;AACnC;AA+CA,MAAMC,KAAW,KAEJC,KAAeC;AAAA,EAC1B,CAAC,EAAE,KAAAC,GAAK,iBAAAC,GAAiB,mBAAAC,EAAA,GAAqBC,OAAQ;AACpD,UAAMC,IAAIC,GAAA,GACJC,KAAUC,GAAA,GACVC,IAAYC,EAAuB,IAAI,GACvCC,IAAUD,EAAwB,IAAI,GACtCE,IAAeF,EAA6B,IAAI,GAChDG,IAAqBH,EAAOR,CAAe,GAC3CY,IAAuBJ,EAAOP,CAAiB;AACrD,IAAAU,EAAmB,UAAUX,GAC7BY,EAAqB,UAAUX;AAE/B,UAAMY,IAAoBL,EAAO,CAAC,GAC5BM,IAAaN,EAAsB,IAAI,GACvCO,IAAiBP,EAAO,EAAK,GAE7B,CAACQ,IAASC,CAAU,IAAIC,EAAS,EAAI,GACrC,CAACC,GAAOC,CAAQ,IAAIF,EAAwB,IAAI,GAChD,CAACG,GAAaC,EAAc,IAAIJ,EAAS,EAAK,GAC9C,CAACK,GAAKC,CAAM,IAAIN,EAAoB,CAAA,CAAE,GACtC,CAACO,GAASC,CAAU,IAAIR,EAAS,EAAK,GACtC,CAACS,GAAeC,CAAgB,IAAIV,EAAiB,EAAE,GACvDW,IAASrB,EAAkB,EAAE;AACnC,IAAAqB,EAAO,UAAUN,GAEjBR,EAAe,UAAUM;AAEzB,UAAMS,IAAaC,EAAY,MAAM;;AACnC,OAAAC,IAAAtB,EAAa,YAAb,QAAAsB,EAAsB;AAAA,IACxB,GAAG,CAAA,CAAE,GAECC,IAAaF,EAAY,MAAM;;AACnC,OAAAC,IAAAtB,EAAa,YAAb,QAAAsB,EAAsB;AAAA,IACxB,GAAG,CAAA,CAAE,GAGCE,IAAqB1B,EAAuB,IAAI,GAChD2B,IAAe3B,EAAO,CAAC,GAEvB4B,IAAc5B,EAAO,CAAC6B,MAAe;;AACzC,YAAMC,IAAYJ,EAAmB;AACrC,UAAI,CAACI,EAAW;AAChB,YAAMC,IAAKD;AAEX,UADmBC,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,eAAe;AAErE,YAAI;AACF,gBAAMC,KAAOR,IAAAtB,EAAa,YAAb,gBAAAsB,EAA4G;AACzH,WAAAS,IAAAD,KAAA,gBAAAA,EAAK,UAAL,QAAAC,EAAA,KAAAD,GAAa,KAAK;AAAA,QACpB,QAAQ;AAAA,QAAe;AAAA,IAE3B,CAAC,GAEKE,IAAyBX,EAAY,MAAM;AAE/C,MAAIG,EAAmB,YACrBA,EAAmB,QAAQ,oBAAoB,UAAUE,EAAY,OAAO,GAC5EF,EAAmB,UAAU,OAE/B,qBAAqBC,EAAa,OAAO;AAEzC,YAAMQ,IAAY,MAAM;;AACtB,cAAML,MAAYN,IAAAzB,EAAU,YAAV,gBAAAyB,EAAmB,cAAc,uBAAsB;AACzE,YAAI,CAACM,GAAW;AACd,UAAAH,EAAa,UAAU,sBAAsBQ,CAAS;AACtD;AAAA,QACF;AACA,QAAAT,EAAmB,UAAUI,GAC7BA,EAAU,iBAAiB,UAAUF,EAAY,SAAS,EAAE,SAAS,IAAM;AAAA,MAC7E;AACA,MAAAD,EAAa,UAAU,sBAAsBQ,CAAS;AAAA,IACxD,GAAG,CAAA,CAAE,GAECC,IAAkBb,EAAY,MAAM;;AACxC,YAAMc,IAAS,CAAC9B,EAAe;AAC/B,MAAAO,GAAeuB,CAAM,IACrBb,IAAApB,EAAqB,YAArB,QAAAoB,EAAA,KAAApB,GAA+BiC,IAE/B,WAAW,MAAM;AACf,cAAMC,IAASvC,EAAU,SACnBwC,IAAYrC,EAAa;AAC/B,QAAI,CAACoC,KAAU,CAACC,MAChBA,EAAU,OAAOD,EAAO,aAAaA,EAAO,YAAY,GAEpDhC,EAAW,WACbiC,EAAU,QAAQjC,EAAW,OAAO,GAGtC4B,EAAA;AAAA,MACF,GAAG,GAAG;AAAA,IACR,GAAG,CAACA,CAAsB,CAAC,GAErBM,KAAYjB,EAAY,MAAM;AAClC,MAAAL,EAAW,CAAAuB,MAAQ,CAACA,CAAI;AAAA,IAC1B,GAAG,CAAA,CAAE,GAECC,KAAiBnB,EAAY,CAACoB,MAAiB;;AACnD,MAAAvB,EAAiBuB,CAAI,IACrBnB,IAAAtB,EAAa,YAAb,QAAAsB,EAAsB,QAAQmB,IAC9BzB,EAAW,EAAK;AAAA,IAClB,GAAG,CAAA,CAAE;AAEL,IAAA0B,GAAoBlD,IAAK,OAAO;AAAA,MAC9B,UAAU4B;AAAA,MACV,UAAUG;AAAA,MACV,iBAAAW;AAAA,MACA,WAAAI;AAAA,IAAA,IACE,CAAClB,GAAYG,GAAYW,GAAiBI,EAAS,CAAC,GAExDK,EAAU,MAAM;AACd,YAAMP,IAASvC,EAAU;AACzB,UAAI,CAACuC,EAAQ;AAEb,MAAA7B,EAAW,EAAI,GACfG,EAAS,IAAI,GACbI,EAAO,CAAA,CAAE,GACTE,EAAW,EAAK,GAChBoB,EAAO,YAAY,IACnBhC,EAAW,UAAU,MACrBD,EAAkB,UAAU;AAE5B,UAAIyC,IAAY;AAGhB,YAAMC,IAAY,OAAO,WAAW,MAAM;AACxC,QAAID,KACJE,EAAA;AAAA,MACF,GAAG,CAAC,GAEEA,IAAO,YAAY;;AACvB,YAAI;AACF,cAAIC,IAAkC1D;AACtC,UAAIA,EAAI,WAAW,OAAO,MAExB0D,IAAY,OADC,MAAMpD,GAAQN,CAAG,GACP,YAAA;AAGzB,gBAAM2D,IAAOC,GAAKF,CAAS;AAC3B,UAAAhD,EAAQ,UAAUiD;AAElB,gBAAMX,IAAYW,EAAK,SAASZ,GAAQ;AAAA,YACtC,SAAS;AAAA,YACT,MAAM;AAAA,YACN,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA,CACT;AACD,UAAApC,EAAa,UAAUqC,GAEvBA,EAAU,OAAO,SAAS,WAAW;AAAA,YACnC,MAAM;AAAA,cACJ,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,eAAe;AAAA,cACf,aAAa;AAAA,cACb,eAAe;AAAA,cACf,SAAS;AAAA,cACT,aAAa;AAAA,cACb,cAAc;AAAA,cACd,cAAc;AAAA,cACd,iBAAiB;AAAA,YAAA;AAAA,YAEnB,GAAG,EAAE,eAAe,kBAAkB,QAAQ,qBAAA;AAAA,YAC9C,IAAI,EAAE,cAAc,qBAAqB,QAAQ,yBAAA;AAAA,YACjD,IAAI,EAAE,QAAQ,2BAAA;AAAA,YACd,IAAI,EAAE,QAAQ,yBAAA;AAAA,YACd,KAAK,EAAE,aAAa,mBAAmB,QAAQ,kBAAA;AAAA,YAC/C,GAAG,EAAE,OAAO,sBAAsB,mBAAmB,kBAAA;AAAA,UAAkB,CACxE,GACDA,EAAU,OAAO,OAAO,SAAS,GAEjC,MAAMW,EAAK,OAGXA,EAAK,UAAU,SAAS,IAAI,EAAE,KAAK,MAAM;;AACvC,gBAAIJ,EAAW;AACf,YAAAzC,EAAkB,UAAU6C,EAAK,UAAU,OAAA;AAE3C,kBAAME,KAAM5B,IAAAtB,EAAa,YAAb,gBAAAsB,EAAsB,mBAC5B6B,MAAMpB,IAAAmB,KAAA,gBAAAA,EAAK,UAAL,gBAAAnB,EAAY,aAAY;AACpC,aAAAqB,IAAAnD,EAAmB,YAAnB,QAAAmD,EAAA,KAAAnD,GAA6BkD,IAAM,GAAGhD,EAAkB;AAAA,UAC1D,CAAC,EAAE,MAAM,MAAM;AAAA,UAAe,CAAC;AAG/B,gBAAMkD,IAAM,MAAML,EAAK,OAAO;AAO9B,cANI,CAACJ,KAAa,MAAM,QAAQS,KAAA,gBAAAA,EAAK,GAAG,KACtCvC,EAAOuC,EAAI,GAAG,GAGhB,MAAMhB,EAAU,QAAA,GAEZO,EAAW;AAEf,UAAArC,EAAW,EAAK,IAChBe,IAAArB,EAAmB,YAAnB,QAAAqB,EAAA,KAAArB,GAA6B,GAAGE,EAAkB,WAAW,IAE7DkC,EAAU,GAAG,aAAa,CAACiB,MAAsB;;AAC/C,kBAAMJ,IAAMI;AAIZ,iBAHIhC,IAAA4B,KAAA,gBAAAA,EAAK,UAAL,QAAA5B,EAAY,QACdlB,EAAW,UAAU8C,EAAI,MAAM,OAE7BnB,KAAAmB,KAAA,gBAAAA,EAAK,UAAL,QAAAnB,GAAY,MAAM;AAEpB,oBAAMwB,IAAYL,EAAI,MAAM,MACtBM,IAAoB,CAAA,GACpBC,KAAU,CAACC,OAAqB;AACpC,2BAAWC,KAAQD,IAAO;AACxB,wBAAME,IAAOD,EAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AACnC,kBAAIC,MAASL,MAAcK,KAAQL,EAAU,SAAS,MAAMK,CAAI,KAAKL,EAAU,SAASK,CAAI,MAC1FJ,EAAQ,KAAKG,EAAK,IAAI,GAEpBA,EAAK,YAAUF,GAAQE,EAAK,QAAQ;AAAA,gBAC1C;AAAA,cACF;AACA,cAAAF,GAAQtC,EAAO,OAAO,GAClBqC,EAAQ,WAAW,KAErBtC,EAAiBsC,EAAQ,CAAC,CAAC;AAAA,YAG/B;AACA,kBAAML,KAAMC,KAAAF,KAAA,gBAAAA,EAAK,UAAL,gBAAAE,GAAY,UAClBS,IAAQ1D,EAAkB;AAChC,YAAI,OAAOgD,KAAQ,YAAYU,IAAQ,OACrCC,KAAA7D,EAAmB,YAAnB,QAAA6D,GAAA,KAAA7D,GAA6BkD,IAAM,GAAGU;AAAA,UAE1C,CAAC;AAAA,QAEH,SAASE,GAAK;AACZ,kBAAQ,MAAM,cAAcA,CAAG,GAC1BnB,MACHlC,EAASjB,EAAE,kBAAkB,CAAC,GAC9Bc,EAAW,EAAK;AAAA,QAEpB;AAAA,MACF;AAEA,aAAO,MAAM;;AACX,QAAAqC,IAAY,IACZ,OAAO,aAAaC,CAAS;AAC7B,YAAI;AAAE,WAAAd,KAAAT,IAAAtB,EAAa,YAAb,gBAAAsB,EAAsB,YAAtB,QAAAS,EAAA,KAAAT;AAAA,QAAmC,QAAQ;AAAA,QAAe;AAChE,YAAI;AAAE,WAAA8B,IAAArD,EAAQ,YAAR,QAAAqD,EAAiB;AAAA,QAAW,QAAQ;AAAA,QAAe;AACzD,QAAApD,EAAa,UAAU,MACvBD,EAAQ,UAAU;AAAA,MACpB;AAAA,IACF,GAAG,CAACV,CAAG,CAAC,GAERsD,EAAU,MAAM;AACd,YAAMqB,IAAW,MAAM;AACrB,cAAM5B,IAASvC,EAAU;AACzB,QAAI,CAACuC,KAAU,CAACpC,EAAa,WAC7BA,EAAa,QAAQ,OAAOoC,EAAO,aAAaA,EAAO,YAAY;AAAA,MACrE;AACA,oBAAO,iBAAiB,UAAU4B,CAAQ,GACnC,MAAM,OAAO,oBAAoB,UAAUA,CAAQ;AAAA,IAC5D,GAAG,CAAA,CAAE,GAELrB,EAAU,OACRX,EAAA,GACO,MAAM;;AACX,2BAAqBP,EAAa,OAAO,IACzCH,IAAAE,EAAmB,YAAnB,QAAAF,EAA4B,oBAAoB,UAAUI,EAAY;AAAA,IACxE,IACC,CAACrC,GAAK2C,CAAsB,CAAC;AAEhC,UAAMiC,KAAW5C,EAAY,CAACoB,MACrBA,MAASxB,GACf,CAACA,CAAa,CAAC,GAEZiD,KAAiB,CAACR,GAAkBS,IAAQ,MAChD,gBAAAC,EAAC,QAAG,OAAO,EAAE,YAAYD,IAAQ,IAAI,KAAK,KACvC,YAAM,IAAI,CAACR,GAAMU,MAAM;AACtB,YAAMC,IAASL,GAASN,EAAK,IAAI;AACjC,+BACG,MAAA,EACC,UAAA;AAAA,QAAA,gBAAAS;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM5B,GAAemB,EAAK,IAAI;AAAA,YACvC,WAAW,sGAAsGW,IAC3G,yDACA,wEACJ;AAAA,YACF,OAAOX,EAAK;AAAA,YAEX,UAAAA,EAAK,MAAM,KAAA;AAAA,UAAK;AAAA,QAAA;AAAA,QAElBA,EAAK,YAAYA,EAAK,SAAS,SAAS,KAAKO,GAAeP,EAAK,UAAUQ,IAAQ,CAAC;AAAA,MAAA,EAAA,GAX9E,GAAGR,EAAK,IAAI,IAAIU,CAAC,EAY1B;AAAA,IAEJ,CAAC,EAAA,CACH;AAGF,WACE,gBAAAE,EAAC,OAAA,EAAI,WAAU,uGACZ,UAAA;AAAA,MAAA9D,KACC,gBAAA2D,EAAC,SAAI,WAAU,+GACb,4BAAC,KAAA,EAAE,WAAU,eAAe,UAAA3D,EAAA,CAAM,EAAA,CACpC;AAAA,MAGDH,MAAW,CAACG,KACX,gBAAA2D,EAAC,OAAA,EAAI,WAAU,kFACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,oHAAA,CAAoH,EAAA,CACrI;AAAA,MAIDvD,EAAI,SAAS,KACZ,gBAAA0D;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,SAASxD,IAAU,IAAI;AAAA,YACvB,eAAeA,IAAU,SAAS;AAAA,UAAA;AAAA,UAGpC,UAAA;AAAA,YAAA,gBAAAwD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,WAAWxD,IAAU,kBAAkB,oBAAA;AAAA,gBAEhD,UAAA;AAAA,kBAAA,gBAAAwD,EAAC,OAAA,EAAI,WAAU,uHACb,UAAA;AAAA,oBAAA,gBAAAH,EAAC,QAAA,EAAK,WAAU,mDAAmD,UAAA3E,EAAE,aAAa,GAAE;AAAA,oBACpF,gBAAA2E;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,SAAS,MAAMpD,EAAW,EAAK;AAAA,wBAC/B,WAAU;AAAA,wBAEV,UAAA,gBAAAoD,EAACI,IAAA,EAAE,WAAU,kBAAA,CAAkB;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACjC,GACF;AAAA,oCACC,OAAA,EAAI,WAAU,oDACZ,UAAAN,GAAerD,CAAG,EAAA,CACrB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAEF,gBAAAuD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,YAAYrD,IAAU,oBAAoB,cAAA;AAAA,gBACnD,SAAS,MAAMC,EAAW,EAAK;AAAA,cAAA;AAAA,YAAA;AAAA,UACjC;AAAA,QAAA;AAAA,MAAA;AAAA,MAIH,CAACP,KACA,gBAAA2D;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKvE;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,YACL,OAAOc,IAAc,SAAS,GAAGzB,EAAQ;AAAA,YACzC,UAAU;AAAA,YACV,YAAY;AAAA,YACZ,UAAU;AAAA,UAAA;AAAA,QACZ;AAAA,MAAA;AAAA,IACF,GAEJ;AAAA,EAEJ;AACF;"}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { jsxs as y, jsx as s } from "react/jsx-runtime";
|
|
2
|
-
import { useState as R, useRef as i, useCallback as T, useEffect as M } from "react";
|
|
3
|
-
import { FileSpreadsheet as z } from "lucide-react";
|
|
4
|
-
import C from "x-data-spreadsheet";
|
|
5
|
-
/* empty css */
|
|
6
|
-
import { u as S, a as E, b as H, x as W, g as k, E as F } from "./index-Bv93wiEK.mjs";
|
|
7
|
-
const I = ({ url: D, fileName: d }) => {
|
|
8
|
-
const m = S(), j = E(), [h, x] = R(!0), [w, N] = R(null), r = i(null), b = i(null), c = i(null), l = i(null), a = i(null), g = i({ width: 0, height: 0 }), o = T(() => {
|
|
9
|
-
if (!r.current) return { width: 800, height: 600 };
|
|
10
|
-
const e = r.current.clientWidth, f = r.current.clientHeight, t = e > 100 ? e : 800, n = f > 100 ? f : 600;
|
|
11
|
-
return { width: t, height: n };
|
|
12
|
-
}, []), p = T(() => {
|
|
13
|
-
if (!r.current || !c.current) return;
|
|
14
|
-
r.current.innerHTML = "", b.current = null;
|
|
15
|
-
const { width: e, height: f } = o(), t = e < 640, n = new C(r.current, {
|
|
16
|
-
mode: "read",
|
|
17
|
-
showToolbar: !1,
|
|
18
|
-
showContextmenu: !1,
|
|
19
|
-
showGrid: !0,
|
|
20
|
-
row: {
|
|
21
|
-
len: 100,
|
|
22
|
-
height: 25
|
|
23
|
-
},
|
|
24
|
-
col: {
|
|
25
|
-
len: 26,
|
|
26
|
-
width: t ? 80 : 100,
|
|
27
|
-
indexWidth: t ? 40 : 60,
|
|
28
|
-
minWidth: t ? 40 : 60
|
|
29
|
-
},
|
|
30
|
-
view: {
|
|
31
|
-
height: () => f,
|
|
32
|
-
width: () => e
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
n.loadData(c.current), b.current = n;
|
|
36
|
-
}, [o]);
|
|
37
|
-
return M(() => {
|
|
38
|
-
if (!r.current) return;
|
|
39
|
-
let e = !0;
|
|
40
|
-
const f = () => {
|
|
41
|
-
if (e) {
|
|
42
|
-
e = !1, g.current = o();
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const t = o(), n = g.current, u = Math.abs(n.width - t.width), v = Math.abs(n.height - t.height);
|
|
46
|
-
u < 10 && v < 10 || (g.current = t, a.current && clearTimeout(a.current), a.current = window.setTimeout(() => {
|
|
47
|
-
c.current && p();
|
|
48
|
-
}, 500));
|
|
49
|
-
};
|
|
50
|
-
return l.current = new ResizeObserver(() => {
|
|
51
|
-
f();
|
|
52
|
-
}), l.current.observe(r.current), () => {
|
|
53
|
-
l.current && l.current.disconnect(), a.current && clearTimeout(a.current);
|
|
54
|
-
};
|
|
55
|
-
}, [o, p]), M(() => {
|
|
56
|
-
let e = !0;
|
|
57
|
-
const f = async () => {
|
|
58
|
-
if (r.current) {
|
|
59
|
-
x(!0), N(null);
|
|
60
|
-
try {
|
|
61
|
-
const n = await H(D, { fetcher: j }), u = W(n, { delimiter: k(d) }), v = F(u.header, u.rows, d);
|
|
62
|
-
if (!e) return;
|
|
63
|
-
c.current = v, p(), x(!1);
|
|
64
|
-
} catch (n) {
|
|
65
|
-
e && (console.error("CSV 解析错误:", n), N(m("csv.load_failed")), x(!1));
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}, t = setTimeout(() => {
|
|
69
|
-
requestAnimationFrame(() => {
|
|
70
|
-
f();
|
|
71
|
-
});
|
|
72
|
-
}, 100);
|
|
73
|
-
return () => {
|
|
74
|
-
e = !1, clearTimeout(t), c.current = null, r.current && (r.current.innerHTML = ""), b.current = null;
|
|
75
|
-
};
|
|
76
|
-
}, [D, d, p]), /* @__PURE__ */ y("div", { className: "rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full", children: [
|
|
77
|
-
h && /* @__PURE__ */ s("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10", children: /* @__PURE__ */ y("div", { className: "rfp-text-center", children: [
|
|
78
|
-
/* @__PURE__ */ s("div", { className: "rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin" }),
|
|
79
|
-
/* @__PURE__ */ s("p", { className: "rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium", children: m("csv.loading") })
|
|
80
|
-
] }) }),
|
|
81
|
-
w && !h && /* @__PURE__ */ s("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10", children: /* @__PURE__ */ y("div", { className: "rfp-text-center rfp-max-w-sm md:rfp-max-w-md rfp-px-4", children: [
|
|
82
|
-
/* @__PURE__ */ s("div", { className: "rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-green-500 rfp-via-emerald-500 rfp-to-teal-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl", children: /* @__PURE__ */ s(z, { className: "rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary" }) }),
|
|
83
|
-
/* @__PURE__ */ s("p", { className: "rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium", children: m("csv.load_failed") }),
|
|
84
|
-
/* @__PURE__ */ s("p", { className: "rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6", children: w })
|
|
85
|
-
] }) }),
|
|
86
|
-
!w && /* @__PURE__ */ s(
|
|
87
|
-
"div",
|
|
88
|
-
{
|
|
89
|
-
ref: r,
|
|
90
|
-
className: "xlsx-spreadsheet-container rfp-w-full rfp-h-full",
|
|
91
|
-
style: { opacity: h ? 0 : 1 }
|
|
92
|
-
}
|
|
93
|
-
)
|
|
94
|
-
] });
|
|
95
|
-
};
|
|
96
|
-
export {
|
|
97
|
-
I as CsvRenderer
|
|
98
|
-
};
|
|
99
|
-
//# sourceMappingURL=index-BcBe6KW7.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BcBe6KW7.mjs","sources":["../../src/renderers/Csv/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { FileSpreadsheet } from 'lucide-react';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport {\n parseCsv,\n guessCsvDelimiter,\n fetchTextUtf8,\n convertCsvToSpreadsheetData,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface CsvRendererProps {\n url: string;\n fileName: string;\n}\n\nexport const CsvRenderer: React.FC<CsvRendererProps> = ({ url, fileName }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const spreadsheetRef = useRef<Spreadsheet | null>(null);\n const sheetDataRef = useRef<Record<string, unknown>[] | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 800, height: 600 };\n const rawWidth = containerRef.current.clientWidth;\n const rawHeight = containerRef.current.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n }, []);\n\n const mountSpreadsheet = useCallback(() => {\n if (!containerRef.current || !sheetDataRef.current) return;\n\n containerRef.current.innerHTML = '';\n spreadsheetRef.current = null;\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.current, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetDataRef.current as unknown as Record<string, unknown>);\n spreadsheetRef.current = s;\n }, [calculateDimensions]);\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const lastDimensions = lastDimensionsRef.current;\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensionsRef.current = newDimensions;\n\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (sheetDataRef.current) {\n mountSpreadsheet();\n }\n }, 500);\n };\n\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, mountSpreadsheet]);\n\n useEffect(() => {\n let isMounted = true;\n\n const loadCsv = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n try {\n const text = await fetchTextUtf8(url, { fetcher });\n const parsed = parseCsv(text, { delimiter: guessCsvDelimiter(fileName) });\n const sheetData = convertCsvToSpreadsheetData(parsed.header, parsed.rows, fileName);\n\n if (!isMounted) return;\n\n sheetDataRef.current = sheetData as unknown as Record<string, unknown>[];\n mountSpreadsheet();\n setLoading(false);\n } catch (err) {\n if (isMounted) {\n console.error('CSV 解析错误:', err);\n setError(t('csv.load_failed'));\n setLoading(false);\n }\n }\n };\n\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n loadCsv();\n });\n }, 100);\n\n return () => {\n isMounted = false;\n clearTimeout(timer);\n sheetDataRef.current = null;\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n spreadsheetRef.current = null;\n };\n }, [url, fileName, mountSpreadsheet]);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('csv.loading')}</p>\n </div>\n </div>\n )}\n\n {error && !loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center rfp-max-w-sm md:rfp-max-w-md rfp-px-4\">\n <div className=\"rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-green-500 rfp-via-emerald-500 rfp-to-teal-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl\">\n <FileSpreadsheet className=\"rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary\" />\n </div>\n <p className=\"rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium\">{t('csv.load_failed')}</p>\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6\">{error}</p>\n </div>\n </div>\n )}\n\n {!error && (\n <div\n ref={containerRef}\n className=\"xlsx-spreadsheet-container rfp-w-full rfp-h-full\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n};\n"],"names":["CsvRenderer","url","fileName","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","containerRef","useRef","spreadsheetRef","sheetDataRef","resizeObserverRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","s","Spreadsheet","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadCsv","text","fetchTextUtf8","parsed","parseCsv","guessCsvDelimiter","sheetData","convertCsvToSpreadsheetData","err","timer","jsxs","jsx","FileSpreadsheet"],"mappings":"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"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { useState as p, useEffect as m } from "react";
|
|
3
|
-
import { u, a as h, b as g } from "./index-Bv93wiEK.mjs";
|
|
4
|
-
import { u as w } from "./useShikiHighlight-DzEAK0S7.mjs";
|
|
5
|
-
const x = (r) => {
|
|
6
|
-
try {
|
|
7
|
-
const n = new DOMParser().parseFromString(r, "application/xml");
|
|
8
|
-
if (n.querySelector("parsererror")) return r;
|
|
9
|
-
const e = new XMLSerializer().serializeToString(n);
|
|
10
|
-
return y(e);
|
|
11
|
-
} catch {
|
|
12
|
-
return r;
|
|
13
|
-
}
|
|
14
|
-
}, y = (r) => {
|
|
15
|
-
const o = " ", n = /(>)(<)(\/*)/g;
|
|
16
|
-
let a = r.replace(n, `$1
|
|
17
|
-
$2$3`), s = 0;
|
|
18
|
-
return a.split(`
|
|
19
|
-
`).map((e) => {
|
|
20
|
-
let l = 0;
|
|
21
|
-
/^<\/\w/.test(e) ? s = Math.max(s - 1, 0) : /^<\w[^>]*[^/]>.*$/.test(e) && !/<.+<\/.+>$/.test(e) && (l = 1);
|
|
22
|
-
const f = o.repeat(s) + e;
|
|
23
|
-
return s += l, f;
|
|
24
|
-
}).join(`
|
|
25
|
-
`);
|
|
26
|
-
}, $ = ({ url: r }) => {
|
|
27
|
-
const o = u(), n = h(), [a, s] = p(""), [e, l] = p(!0), [f, c] = p(null), { html: d } = w(a, "xml");
|
|
28
|
-
return m(() => {
|
|
29
|
-
(async () => {
|
|
30
|
-
try {
|
|
31
|
-
l(!0), c(null);
|
|
32
|
-
const i = await g(r, { fetcher: n });
|
|
33
|
-
s(x(i));
|
|
34
|
-
} catch (i) {
|
|
35
|
-
console.error(i), c(o("xml.load_failed"));
|
|
36
|
-
} finally {
|
|
37
|
-
l(!1);
|
|
38
|
-
}
|
|
39
|
-
})();
|
|
40
|
-
}, [r]), e ? /* @__PURE__ */ t("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ t("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" }) }) : f ? /* @__PURE__ */ t("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full", children: /* @__PURE__ */ t("div", { className: "rfp-text-fg-secondary rfp-text-center", children: /* @__PURE__ */ t("p", { className: "rfp-text-lg", children: f }) }) }) : /* @__PURE__ */ t("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg", children: d ? /* @__PURE__ */ t(
|
|
41
|
-
"div",
|
|
42
|
-
{
|
|
43
|
-
className: "rfp-shiki-wrapper with-line-numbers",
|
|
44
|
-
dangerouslySetInnerHTML: { __html: d }
|
|
45
|
-
}
|
|
46
|
-
) : /* @__PURE__ */ t("pre", { className: "rfp-p-6 rfp-text-fg-primary rfp-font-mono rfp-text-sm rfp-whitespace-pre-wrap rfp-break-words", children: a }) });
|
|
47
|
-
};
|
|
48
|
-
export {
|
|
49
|
-
$ as XmlRenderer
|
|
50
|
-
};
|
|
51
|
-
//# sourceMappingURL=index-BdYkTSTt.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BdYkTSTt.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';\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 load = async () => {\n try {\n setLoading(true);\n setError(null);\n const raw = await fetchTextUtf8(url, { fetcher });\n setContent(prettyPrintXml(raw));\n } catch (err) {\n console.error(err);\n setError(t('xml.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\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 (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-text-fg-secondary rfp-text-center\">\n <p className=\"rfp-text-lg\">{error}</p>\n </div>\n </div>\n );\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","raw","fetchTextUtf8","err","jsx"],"mappings":";;;;AAcA,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;AAmB9D,SAjBAS,EAAU,MAAM;AAcd,KAba,YAAY;AACvB,UAAI;AACF,QAAAL,EAAW,EAAI,GACfE,EAAS,IAAI;AACb,cAAMI,IAAM,MAAMC,EAAchB,GAAK,EAAE,SAAAG,GAAS;AAChD,QAAAG,EAAWnB,EAAe4B,CAAG,CAAC;AAAA,MAChC,SAASE,GAAK;AACZ,gBAAQ,MAAMA,CAAG,GACjBN,EAASV,EAAE,iBAAiB,CAAC;AAAA,MAC/B,UAAA;AACE,QAAAQ,EAAW,EAAK;AAAA,MAClB;AAAA,IACF,GACA;AAAA,EACF,GAAG,CAACT,CAAG,CAAC,GAEJQ,IAEA,gBAAAU,EAAC,SAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,qHAAoH,EAAA,CACrI,IAIAR,IAEA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,sEACb,4BAAC,OAAA,EAAI,WAAU,yCACb,UAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,eAAe,UAAAR,EAAA,CAAM,GACpC,GACF,IAKF,gBAAAQ,EAAC,OAAA,EAAI,WAAU,0DACZ,UAAAN,IACC,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,yBAAyB,EAAE,QAAQN,EAAA;AAAA,IAAY;AAAA,EAAA,IAGjD,gBAAAM,EAAC,OAAA,EAAI,WAAU,iGACZ,aACH,GAEJ;AAEJ;"}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { jsxs as b, jsx as i } from "react/jsx-runtime";
|
|
2
|
-
import { useState as M, useRef as u, useCallback as z, useEffect as L } from "react";
|
|
3
|
-
import { Presentation as B } from "lucide-react";
|
|
4
|
-
import { init as C } from "pptx-preview";
|
|
5
|
-
import { u as F, a as S } from "./index-Bv93wiEK.mjs";
|
|
6
|
-
const V = ({ url: y, tiled: a = !0 }) => {
|
|
7
|
-
const s = F(), _ = S(), [v, w] = M(!0), [N, T] = M(null), [E, P] = M(0), n = u(null), o = u(null), x = u(null), d = u(null), m = u(null), k = u({ width: 0, height: 0 }), c = z(() => {
|
|
8
|
-
var t;
|
|
9
|
-
if (!n.current) return { width: 960, height: 540 };
|
|
10
|
-
const e = n.current.clientWidth, r = ((t = n.current.parentElement) == null ? void 0 : t.clientWidth) || 0, p = e > 100 ? e : r > 100 ? r : 300, l = Math.floor(p * 9 / 16);
|
|
11
|
-
return { width: p, height: l };
|
|
12
|
-
}, []), W = z(async () => {
|
|
13
|
-
if (!(!n.current || !d.current || E === 0))
|
|
14
|
-
try {
|
|
15
|
-
if (o.current)
|
|
16
|
-
try {
|
|
17
|
-
o.current.destroy();
|
|
18
|
-
} catch {
|
|
19
|
-
}
|
|
20
|
-
n.current.innerHTML = "";
|
|
21
|
-
const e = c(), r = C(n.current, {
|
|
22
|
-
width: e.width,
|
|
23
|
-
height: a ? e.height * E : e.height,
|
|
24
|
-
mode: a ? "list" : "slide"
|
|
25
|
-
});
|
|
26
|
-
o.current = r, await r.preview(d.current);
|
|
27
|
-
} catch {
|
|
28
|
-
}
|
|
29
|
-
}, [c, a, E]);
|
|
30
|
-
return L(() => {
|
|
31
|
-
if (!n.current) return;
|
|
32
|
-
let e = !0;
|
|
33
|
-
const r = () => {
|
|
34
|
-
if (e) {
|
|
35
|
-
e = !1, k.current = c();
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const p = c(), l = k.current, t = Math.abs(l.width - p.width), f = Math.abs(l.height - p.height);
|
|
39
|
-
t < 10 && f < 10 || (k.current = p, m.current && clearTimeout(m.current), m.current = window.setTimeout(() => {
|
|
40
|
-
o.current && d.current && W();
|
|
41
|
-
}, 800));
|
|
42
|
-
};
|
|
43
|
-
return x.current = new ResizeObserver(() => {
|
|
44
|
-
r();
|
|
45
|
-
}), x.current.observe(n.current), () => {
|
|
46
|
-
x.current && x.current.disconnect(), m.current && clearTimeout(m.current);
|
|
47
|
-
};
|
|
48
|
-
}, [c, W]), L(() => {
|
|
49
|
-
let e = !0, r = null;
|
|
50
|
-
const p = async () => {
|
|
51
|
-
if (n.current) {
|
|
52
|
-
w(!0), T(null), r = setTimeout(() => {
|
|
53
|
-
e && (T(s("pptx.timeout")), w(!1));
|
|
54
|
-
}, 3e4);
|
|
55
|
-
try {
|
|
56
|
-
const t = await _(y, {
|
|
57
|
-
mode: "cors",
|
|
58
|
-
credentials: "omit",
|
|
59
|
-
redirect: "follow"
|
|
60
|
-
});
|
|
61
|
-
if (!t.ok)
|
|
62
|
-
throw t.status === 404 ? new Error(s("pptx.not_found")) : t.status === 403 ? new Error("无权限访问此文件") : t.status >= 500 ? new Error("服务器错误,请稍后重试") : new Error(`文件加载失败 (${t.status})`);
|
|
63
|
-
const f = await t.arrayBuffer();
|
|
64
|
-
if (f.byteLength === 0)
|
|
65
|
-
throw new Error("文件为空");
|
|
66
|
-
if (d.current = f, !e) return;
|
|
67
|
-
const h = document.createElement("div");
|
|
68
|
-
h.style.cssText = "position:absolute;left:-9999px;top:-9999px;visibility:hidden", document.body.appendChild(h);
|
|
69
|
-
try {
|
|
70
|
-
const R = C(h, {
|
|
71
|
-
width: 100,
|
|
72
|
-
height: 100,
|
|
73
|
-
mode: "slide"
|
|
74
|
-
});
|
|
75
|
-
try {
|
|
76
|
-
await R.preview(f);
|
|
77
|
-
} catch {
|
|
78
|
-
throw new Error(s("pptx.invalid_format"));
|
|
79
|
-
}
|
|
80
|
-
const g = R.slideCount;
|
|
81
|
-
if (!g || g === 0)
|
|
82
|
-
throw new Error(s("pptx.no_pages"));
|
|
83
|
-
if (R.destroy(), !e) return;
|
|
84
|
-
P(g), n.current && (n.current.innerHTML = "");
|
|
85
|
-
const D = c(), j = C(n.current, {
|
|
86
|
-
width: D.width,
|
|
87
|
-
height: a ? D.height * g : D.height,
|
|
88
|
-
mode: a ? "list" : "slide"
|
|
89
|
-
});
|
|
90
|
-
o.current = j, await j.preview(f), r && (clearTimeout(r), r = null), e && w(!1);
|
|
91
|
-
} finally {
|
|
92
|
-
document.body.contains(h) && document.body.removeChild(h);
|
|
93
|
-
}
|
|
94
|
-
} catch (t) {
|
|
95
|
-
if (r && (clearTimeout(r), r = null), e) {
|
|
96
|
-
let f = s("pptx.parse_failed");
|
|
97
|
-
t instanceof Error ? f = t.message : typeof t == "string" && (f = t), T(f), w(!1);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}, l = setTimeout(() => {
|
|
102
|
-
requestAnimationFrame(() => {
|
|
103
|
-
requestAnimationFrame(() => {
|
|
104
|
-
p();
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}, 150);
|
|
108
|
-
return () => {
|
|
109
|
-
if (e = !1, clearTimeout(l), r && clearTimeout(r), d.current = null, P(0), o.current)
|
|
110
|
-
try {
|
|
111
|
-
o.current.destroy();
|
|
112
|
-
} catch {
|
|
113
|
-
}
|
|
114
|
-
o.current = null;
|
|
115
|
-
};
|
|
116
|
-
}, [y, c, a]), /* @__PURE__ */ b("div", { className: "rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full", children: [
|
|
117
|
-
v && /* @__PURE__ */ i("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10", children: /* @__PURE__ */ b("div", { className: "rfp-text-center", children: [
|
|
118
|
-
/* @__PURE__ */ i("div", { className: "rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin" }),
|
|
119
|
-
/* @__PURE__ */ i("p", { className: "rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium", children: s("pptx.loading") })
|
|
120
|
-
] }) }),
|
|
121
|
-
N && !v && /* @__PURE__ */ i("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10", children: /* @__PURE__ */ b("div", { className: "rfp-text-center rfp-max-w-sm md:rfp-max-w-md rfp-px-4", children: [
|
|
122
|
-
/* @__PURE__ */ i("div", { className: "rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-orange-500 rfp-via-red-500 rfp-to-pink-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl", children: /* @__PURE__ */ i(B, { className: "rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary" }) }),
|
|
123
|
-
/* @__PURE__ */ i("p", { className: "rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium", children: s("pptx.load_failed") }),
|
|
124
|
-
/* @__PURE__ */ i("p", { className: "rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6", children: N }),
|
|
125
|
-
/* @__PURE__ */ b(
|
|
126
|
-
"a",
|
|
127
|
-
{
|
|
128
|
-
href: y,
|
|
129
|
-
download: !0,
|
|
130
|
-
className: "rfp-inline-flex rfp-items-center rfp-gap-2 rfp-px-4 rfp-py-2 md:rfp-px-6 md:rfp-py-3 rfp-bg-gradient-to-r rfp-from-purple-500 rfp-to-pink-500 rfp-text-fg-primary rfp-text-sm md:rfp-text-base rfp-rounded-lg md:rfp-rounded-xl hover:rfp-scale-105 rfp-transition-all rfp-shadow-lg",
|
|
131
|
-
children: [
|
|
132
|
-
/* @__PURE__ */ i("svg", { className: "rfp-w-4 rfp-h-4 md:rfp-w-5 md:rfp-h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ i("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" }) }),
|
|
133
|
-
s("common.download")
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
),
|
|
137
|
-
/* @__PURE__ */ i("p", { className: "rfp-text-xs rfp-text-fg-muted rfp-mt-3 md:rfp-mt-4", children: "提示:可以使用 Microsoft PowerPoint 或 WPS 打开" })
|
|
138
|
-
] }) }),
|
|
139
|
-
!N && /* @__PURE__ */ i(
|
|
140
|
-
"div",
|
|
141
|
-
{
|
|
142
|
-
ref: n,
|
|
143
|
-
className: "pptx-wrapper rfp-w-full rfp-max-w-full md:rfp-max-w-6xl",
|
|
144
|
-
style: { opacity: v ? 0 : 1 }
|
|
145
|
-
}
|
|
146
|
-
)
|
|
147
|
-
] });
|
|
148
|
-
};
|
|
149
|
-
export {
|
|
150
|
-
V as PptxRenderer
|
|
151
|
-
};
|
|
152
|
-
//# sourceMappingURL=index-BqEuP_8r.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BqEuP_8r.mjs","sources":["../../src/renderers/Pptx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { Presentation } from 'lucide-react';\nimport { init } from 'pptx-preview';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\n\ninterface PptxRendererProps {\n url: string;\n /** 是否平铺展示所有页面,默认 true */\n tiled?: boolean;\n}\n\nexport const PptxRenderer: React.FC<PptxRendererProps> = ({ url, tiled = true }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [slideCount, setSlideCount] = useState(0);\n const containerRef = useRef<HTMLDivElement>(null);\n const previewerRef = useRef<ReturnType<typeof init> | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const arrayBufferRef = useRef<ArrayBuffer | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n // 计算容器尺寸,带回退逻辑\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 960, height: 540 };\n const rawWidth = containerRef.current.clientWidth;\n const parentWidth = containerRef.current.parentElement?.clientWidth || 0;\n // 如果容器宽度太小,回退到父容器宽度或默认最小值\n const containerWidth = rawWidth > 100 ? rawWidth : (parentWidth > 100 ? parentWidth : 300);\n // 16:9 比例\n const height = Math.floor(containerWidth * 9 / 16);\n return { width: containerWidth, height };\n }, []);\n\n // 重新初始化预览器\n const reinitializePreviewer = useCallback(async () => {\n if (!containerRef.current || !arrayBufferRef.current || slideCount === 0) return;\n\n try {\n // 销毁旧的预览器\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n\n // 清空容器\n containerRef.current.innerHTML = '';\n\n // 获取当前容器尺寸\n const currentDimensions = calculateDimensions();\n\n // 初始化新的预览器,平铺模式下高度按页数计算\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * slideCount : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 重新预览\n await previewer.preview(arrayBufferRef.current);\n } catch {\n // 重新初始化失败,静默处理\n }\n }, [calculateDimensions, tiled, slideCount]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n // 跳过初始渲染时的尺寸检查\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n\n // 检查尺寸是否真正变化(至少变化10px才触发)\n const lastDimensions = lastDimensionsRef.current;\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) {\n return;\n }\n\n // 更新最后的尺寸\n lastDimensionsRef.current = newDimensions;\n\n // 清除之前的定时器\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // 防抖:800ms 后重新初始化预览器\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (previewerRef.current && arrayBufferRef.current) {\n reinitializePreviewer();\n }\n }, 800);\n };\n\n // 创建 ResizeObserver\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n // 开始观察容器\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, reinitializePreviewer]);\n\n useEffect(() => {\n let isMounted = true;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const loadPptx = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n // 设置30秒超时\n timeoutId = setTimeout(() => {\n if (isMounted) {\n setError(t('pptx.timeout'));\n setLoading(false);\n }\n }, 30000);\n\n try {\n // 获取文件,处理 CORS 和重定向\n const response = await fetcher(url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(t('pptx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else if (response.status >= 500) {\n throw new Error('服务器错误,请稍后重试');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n // 验证文件大小\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n arrayBufferRef.current = arrayBuffer;\n\n if (!isMounted) return;\n\n // 步骤 1: 创建隐藏容器,预处理获取 slideCount\n const hiddenContainer = document.createElement('div');\n hiddenContainer.style.cssText = 'position:absolute;left:-9999px;top:-9999px;visibility:hidden';\n document.body.appendChild(hiddenContainer);\n\n try {\n // 在隐藏容器中初始化临时预览器获取页数\n const tempPreviewer = init(hiddenContainer, {\n width: 100,\n height: 100,\n mode: 'slide',\n });\n\n try {\n await tempPreviewer.preview(arrayBuffer);\n } catch {\n throw new Error(t('pptx.invalid_format'));\n }\n\n const count = tempPreviewer.slideCount;\n\n if (!count || count === 0) {\n throw new Error(t('pptx.no_pages'));\n }\n\n // 销毁临时预览器\n tempPreviewer.destroy();\n\n if (!isMounted) return;\n\n // 保存 slideCount\n setSlideCount(count);\n\n // 步骤 2: 清空真实容器并初始化\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n\n const currentDimensions = calculateDimensions();\n\n // 步骤 3: 初始化真实预览器,平铺模式下使用正确的总高度\n const previewer = init(containerRef.current, {\n width: currentDimensions.width,\n height: tiled ? currentDimensions.height * count : currentDimensions.height,\n mode: tiled ? 'list' : 'slide',\n });\n previewerRef.current = previewer;\n\n // 步骤 4: 预览 PPTX\n await previewer.preview(arrayBuffer);\n\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n setLoading(false);\n }\n } finally {\n // 移除隐藏容器\n if (document.body.contains(hiddenContainer)) {\n document.body.removeChild(hiddenContainer);\n }\n }\n } catch (err) {\n // 清除超时定时器\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (isMounted) {\n let errorMsg = t('pptx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n } else if (typeof err === 'string') {\n errorMsg = err;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n // 延迟执行,使用 requestAnimationFrame 确保 DOM 已准备好\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n loadPptx();\n });\n });\n }, 150);\n\n // 清理函数\n return () => {\n isMounted = false;\n clearTimeout(timer);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n arrayBufferRef.current = null;\n setSlideCount(0);\n if (previewerRef.current) {\n try {\n previewerRef.current.destroy();\n } catch {\n // 忽略销毁错误\n }\n }\n previewerRef.current = null;\n };\n }, [url, calculateDimensions, tiled]);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {/* 加载状态 - 绝对定位覆盖 */}\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('pptx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 - 绝对定位覆盖 */}\n {error && !loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center rfp-max-w-sm md:rfp-max-w-md rfp-px-4\">\n <div className=\"rfp-w-24 rfp-h-24 md:rfp-w-32 md:rfp-h-32 rfp-mx-auto rfp-mb-4 md:rfp-mb-6 rfp-rounded-2xl md:rfp-rounded-3xl rfp-bg-gradient-to-br rfp-from-orange-500 rfp-via-red-500 rfp-to-pink-500 rfp-flex rfp-items-center rfp-justify-center rfp-shadow-2xl\">\n <Presentation className=\"rfp-w-12 rfp-h-12 md:rfp-w-16 md:rfp-h-16 rfp-text-fg-primary\" />\n </div>\n <p className=\"rfp-text-lg md:rfp-text-xl rfp-text-fg-primary rfp-mb-2 md:rfp-mb-3 rfp-font-medium\">{t('pptx.load_failed')}</p>\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-tertiary rfp-mb-4 md:rfp-mb-6\">\n {error}\n </p>\n <a\n href={url}\n download\n className=\"rfp-inline-flex rfp-items-center rfp-gap-2 rfp-px-4 rfp-py-2 md:rfp-px-6 md:rfp-py-3 rfp-bg-gradient-to-r rfp-from-purple-500 rfp-to-pink-500 rfp-text-fg-primary rfp-text-sm md:rfp-text-base rfp-rounded-lg md:rfp-rounded-xl hover:rfp-scale-105 rfp-transition-all rfp-shadow-lg\"\n >\n <svg className=\"rfp-w-4 rfp-h-4 md:rfp-w-5 md:rfp-h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n {t('common.download')}\n </a>\n <p className=\"rfp-text-xs rfp-text-fg-muted rfp-mt-3 md:rfp-mt-4\">\n 提示:可以使用 Microsoft PowerPoint 或 WPS 打开\n </p>\n </div>\n </div>\n )}\n\n {/* PPT 容器 - 仅在非错误状态下渲染 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"pptx-wrapper rfp-w-full rfp-max-w-full md:rfp-max-w-6xl\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n};\n"],"names":["PptxRenderer","url","tiled","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","slideCount","setSlideCount","containerRef","useRef","previewerRef","resizeObserverRef","arrayBufferRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","parentWidth","_a","containerWidth","height","reinitializePreviewer","currentDimensions","previewer","init","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","timeoutId","loadPptx","response","arrayBuffer","hiddenContainer","tempPreviewer","count","err","errorMsg","timer","jsxs","jsx","Presentation"],"mappings":"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"}
|