@eternalheart/react-file-preview 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +437 -60
  2. package/README.zh-CN.md +437 -60
  3. package/lib/FilePreviewContent.d.ts +1 -0
  4. package/lib/FilePreviewContent.d.ts.map +1 -1
  5. package/lib/FilePreviewEmbed.d.ts +2 -0
  6. package/lib/FilePreviewEmbed.d.ts.map +1 -1
  7. package/lib/FilePreviewModal.d.ts +2 -0
  8. package/lib/FilePreviewModal.d.ts.map +1 -1
  9. package/lib/chunks/index-BBYKNNLb.mjs +329 -0
  10. package/lib/chunks/index-BBYKNNLb.mjs.map +1 -0
  11. package/lib/chunks/index-BFh22D_W.mjs +78 -0
  12. package/lib/chunks/index-BFh22D_W.mjs.map +1 -0
  13. package/lib/chunks/{index-DoFsoBKL.mjs → index-BKXvtJh5.mjs} +27 -25
  14. package/lib/chunks/index-BKXvtJh5.mjs.map +1 -0
  15. package/lib/chunks/index-Bw3Fh4b5.mjs +116 -0
  16. package/lib/chunks/index-Bw3Fh4b5.mjs.map +1 -0
  17. package/lib/chunks/{index-kALp0tqz.mjs → index-CEC_DHgr.mjs} +22 -20
  18. package/lib/chunks/index-CEC_DHgr.mjs.map +1 -0
  19. package/lib/chunks/{index-CzM2mxrD.mjs → index-COOUxB5e.mjs} +130 -128
  20. package/lib/chunks/{index-CzM2mxrD.mjs.map → index-COOUxB5e.mjs.map} +1 -1
  21. package/lib/chunks/index-CU1Lc3lV.mjs +120 -0
  22. package/lib/chunks/index-CU1Lc3lV.mjs.map +1 -0
  23. package/lib/chunks/index-CgFv7B_G.mjs +359 -0
  24. package/lib/chunks/index-CgFv7B_G.mjs.map +1 -0
  25. package/lib/chunks/index-Cn4ZyhGM.mjs +587 -0
  26. package/lib/chunks/index-Cn4ZyhGM.mjs.map +1 -0
  27. package/lib/chunks/{index-DaAXRBWL.mjs → index-DGNNEnWE.mjs} +864 -862
  28. package/lib/chunks/{index-DaAXRBWL.mjs.map → index-DGNNEnWE.mjs.map} +1 -1
  29. package/lib/chunks/index-DLk08ylq.mjs +313 -0
  30. package/lib/chunks/index-DLk08ylq.mjs.map +1 -0
  31. package/lib/chunks/index-DVtPyN-s.mjs +200 -0
  32. package/lib/chunks/index-DVtPyN-s.mjs.map +1 -0
  33. package/lib/chunks/index-DreA69iU.mjs +2409 -0
  34. package/lib/chunks/index-DreA69iU.mjs.map +1 -0
  35. package/lib/chunks/{index-Cp68OevR.mjs → index-Dta7iGov.mjs} +1299 -1297
  36. package/lib/chunks/{index-Cp68OevR.mjs.map → index-Dta7iGov.mjs.map} +1 -1
  37. package/lib/chunks/index-fQGAUFAX.mjs +275 -0
  38. package/lib/chunks/index-fQGAUFAX.mjs.map +1 -0
  39. package/lib/chunks/{index-C_BJatqr.mjs → index-fSw6Hl5e.mjs} +42 -40
  40. package/lib/chunks/index-fSw6Hl5e.mjs.map +1 -0
  41. package/lib/chunks/index-jvNrkVkp.mjs +291 -0
  42. package/lib/chunks/index-jvNrkVkp.mjs.map +1 -0
  43. package/lib/chunks/index-oVJyD-FV.mjs +107 -0
  44. package/lib/chunks/index-oVJyD-FV.mjs.map +1 -0
  45. package/lib/chunks/{index-DuP0Tlpo.mjs → index-vRLKumL8.mjs} +43 -41
  46. package/lib/chunks/index-vRLKumL8.mjs.map +1 -0
  47. package/lib/chunks/useShikiHighlight-C6nJcETW.mjs +36 -0
  48. package/lib/chunks/useShikiHighlight-C6nJcETW.mjs.map +1 -0
  49. package/lib/components/preview/FilePreviewToolbar.d.ts +1 -0
  50. package/lib/components/preview/FilePreviewToolbar.d.ts.map +1 -1
  51. package/lib/components/preview/ToolbarButton.d.ts +3 -1
  52. package/lib/components/preview/ToolbarButton.d.ts.map +1 -1
  53. package/lib/hooks/index.d.ts +0 -6
  54. package/lib/hooks/index.d.ts.map +1 -1
  55. package/lib/hooks/useShikiHighlight.d.ts +3 -1
  56. package/lib/hooks/useShikiHighlight.d.ts.map +1 -1
  57. package/lib/index.cjs +32 -30
  58. package/lib/index.cjs.map +1 -1
  59. package/lib/index.css +1 -1
  60. package/lib/index.mjs +1 -1
  61. package/lib/renderers/Audio/index.d.ts +2 -1
  62. package/lib/renderers/Audio/index.d.ts.map +1 -1
  63. package/lib/renderers/Csv/index.d.ts +2 -1
  64. package/lib/renderers/Csv/index.d.ts.map +1 -1
  65. package/lib/renderers/Docx/index.d.ts +2 -1
  66. package/lib/renderers/Docx/index.d.ts.map +1 -1
  67. package/lib/renderers/Epub/index.d.ts +2 -3
  68. package/lib/renderers/Epub/index.d.ts.map +1 -1
  69. package/lib/renderers/Font/index.d.ts +2 -1
  70. package/lib/renderers/Font/index.d.ts.map +1 -1
  71. package/lib/renderers/Image/index.d.ts +6 -7
  72. package/lib/renderers/Image/index.d.ts.map +1 -1
  73. package/lib/renderers/Json/index.d.ts +2 -1
  74. package/lib/renderers/Json/index.d.ts.map +1 -1
  75. package/lib/renderers/Markdown/index.d.ts +2 -2
  76. package/lib/renderers/Markdown/index.d.ts.map +1 -1
  77. package/lib/renderers/Mobi/index.d.ts +2 -3
  78. package/lib/renderers/Mobi/index.d.ts.map +1 -1
  79. package/lib/renderers/Msg/index.d.ts +2 -1
  80. package/lib/renderers/Msg/index.d.ts.map +1 -1
  81. package/lib/renderers/Pdf/index.d.ts +4 -8
  82. package/lib/renderers/Pdf/index.d.ts.map +1 -1
  83. package/lib/renderers/Pptx/index.d.ts +2 -1
  84. package/lib/renderers/Pptx/index.d.ts.map +1 -1
  85. package/lib/renderers/Subtitle/index.d.ts +2 -1
  86. package/lib/renderers/Subtitle/index.d.ts.map +1 -1
  87. package/lib/renderers/Text/index.d.ts +2 -3
  88. package/lib/renderers/Text/index.d.ts.map +1 -1
  89. package/lib/renderers/Video/index.d.ts +2 -1
  90. package/lib/renderers/Video/index.d.ts.map +1 -1
  91. package/lib/renderers/Xlsx/index.d.ts +2 -1
  92. package/lib/renderers/Xlsx/index.d.ts.map +1 -1
  93. package/lib/renderers/Xml/index.d.ts +2 -1
  94. package/lib/renderers/Xml/index.d.ts.map +1 -1
  95. package/lib/renderers/Zip/index.d.ts +7 -2
  96. package/lib/renderers/Zip/index.d.ts.map +1 -1
  97. package/lib/renderers/base.types.d.ts +38 -0
  98. package/lib/renderers/base.types.d.ts.map +1 -0
  99. package/lib/renderers/registry.d.ts +36 -0
  100. package/lib/renderers/registry.d.ts.map +1 -0
  101. package/lib/renderers/toolbar.types.d.ts +2 -0
  102. package/lib/renderers/toolbar.types.d.ts.map +1 -1
  103. package/lib/toolbar/renderItems.d.ts.map +1 -1
  104. package/package.json +3 -3
  105. package/lib/chunks/index-0v5STX5f.mjs +0 -105
  106. package/lib/chunks/index-0v5STX5f.mjs.map +0 -1
  107. package/lib/chunks/index-10O8tfTH.mjs +0 -529
  108. package/lib/chunks/index-10O8tfTH.mjs.map +0 -1
  109. package/lib/chunks/index-BCyv1HM9.mjs +0 -175
  110. package/lib/chunks/index-BCyv1HM9.mjs.map +0 -1
  111. package/lib/chunks/index-Bo90aGhy.mjs +0 -114
  112. package/lib/chunks/index-Bo90aGhy.mjs.map +0 -1
  113. package/lib/chunks/index-CEeKt7L3.mjs +0 -2808
  114. package/lib/chunks/index-CEeKt7L3.mjs.map +0 -1
  115. package/lib/chunks/index-CWKbnvW6.mjs +0 -270
  116. package/lib/chunks/index-CWKbnvW6.mjs.map +0 -1
  117. package/lib/chunks/index-C_BJatqr.mjs.map +0 -1
  118. package/lib/chunks/index-Cbz5Z6ZK.mjs +0 -263
  119. package/lib/chunks/index-Cbz5Z6ZK.mjs.map +0 -1
  120. package/lib/chunks/index-DTYBFuAH.mjs +0 -357
  121. package/lib/chunks/index-DTYBFuAH.mjs.map +0 -1
  122. package/lib/chunks/index-DoFsoBKL.mjs.map +0 -1
  123. package/lib/chunks/index-DuP0Tlpo.mjs.map +0 -1
  124. package/lib/chunks/index-Dv3RQz86.mjs +0 -270
  125. package/lib/chunks/index-Dv3RQz86.mjs.map +0 -1
  126. package/lib/chunks/index-QfpHck8N.mjs +0 -55
  127. package/lib/chunks/index-QfpHck8N.mjs.map +0 -1
  128. package/lib/chunks/index-gjSQeou7.mjs +0 -194
  129. package/lib/chunks/index-gjSQeou7.mjs.map +0 -1
  130. package/lib/chunks/index-kALp0tqz.mjs.map +0 -1
  131. package/lib/chunks/index-kCeSnFs-.mjs +0 -54
  132. package/lib/chunks/index-kCeSnFs-.mjs.map +0 -1
  133. package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs +0 -23
  134. package/lib/chunks/useShikiHighlight-BA9qgdGA.mjs.map +0 -1
  135. package/lib/hooks/rendererReducer.d.ts +0 -10
  136. package/lib/hooks/rendererReducer.d.ts.map +0 -1
  137. package/lib/hooks/types.d.ts +0 -152
  138. package/lib/hooks/types.d.ts.map +0 -1
  139. package/lib/hooks/useBookRenderer.d.ts +0 -14
  140. package/lib/hooks/useBookRenderer.d.ts.map +0 -1
  141. package/lib/hooks/useFilePreviewState.d.ts +0 -10
  142. package/lib/hooks/useFilePreviewState.d.ts.map +0 -1
  143. package/lib/hooks/useImageAutoFit.d.ts +0 -13
  144. package/lib/hooks/useImageAutoFit.d.ts.map +0 -1
  145. package/lib/hooks/useToolbarConfig.d.ts +0 -25
  146. package/lib/hooks/useToolbarConfig.d.ts.map +0 -1
  147. package/lib/renderers/Epub/toolbar.d.ts +0 -13
  148. package/lib/renderers/Epub/toolbar.d.ts.map +0 -1
  149. package/lib/renderers/Image/toolbar.d.ts +0 -15
  150. package/lib/renderers/Image/toolbar.d.ts.map +0 -1
  151. package/lib/renderers/Markdown/toolbar.d.ts +0 -9
  152. package/lib/renderers/Markdown/toolbar.d.ts.map +0 -1
  153. package/lib/renderers/Mobi/toolbar.d.ts +0 -13
  154. package/lib/renderers/Mobi/toolbar.d.ts.map +0 -1
  155. package/lib/renderers/Pdf/toolbar.d.ts +0 -16
  156. package/lib/renderers/Pdf/toolbar.d.ts.map +0 -1
  157. package/lib/renderers/Text/toolbar.d.ts +0 -12
  158. package/lib/renderers/Text/toolbar.d.ts.map +0 -1
  159. package/lib/renderers/Zip/toolbar.d.ts +0 -13
  160. package/lib/renderers/Zip/toolbar.d.ts.map +0 -1
  161. package/lib/toolbar/registry.d.ts +0 -51
  162. package/lib/toolbar/registry.d.ts.map +0 -1
@@ -0,0 +1,275 @@
1
+ import { jsx as o, jsxs as F } from "react/jsx-runtime";
2
+ import { forwardRef as Lt, useRef as W, useState as d, useCallback as c, useEffect as C, useImperativeHandle as Pt } from "react";
3
+ import { List as Ft, ChevronLeft as Wt, ChevronRight as _t, Minimize2 as $t, Maximize2 as jt, X as It } from "lucide-react";
4
+ import "foliate-js/view.js";
5
+ import { u as Ht, a as Dt } from "./index-DreA69iU.mjs";
6
+ import { R as Xt } from "./RendererError-D5i8eSpN.mjs";
7
+ const Gt = `
8
+ @namespace epub "http://www.idpf.org/2007/ops";
9
+ html { color-scheme: light; }
10
+ body {
11
+ background: #ffffff !important;
12
+ color: #1a1a1a !important;
13
+ font-family: "Noto Serif SC", "Source Han Serif SC", Georgia, "Times New Roman", serif !important;
14
+ font-size: 16px !important;
15
+ line-height: 2 !important;
16
+ max-width: 100% !important;
17
+ box-sizing: border-box !important;
18
+ word-break: break-word !important;
19
+ overflow-wrap: break-word !important;
20
+ }
21
+ p, li, blockquote, dd { line-height: 2; text-align: justify; }
22
+ p { text-indent: 2em; margin: 0.8em 0; }
23
+ h1 { text-align: center; margin: 1.5em 0 1em; }
24
+ h2 { margin: 1.2em 0 0.8em; }
25
+ h3 { margin: 1em 0 0.6em; }
26
+ img { max-width: 100% !important; height: auto !important; }
27
+ a { color: #2563eb; text-decoration: none; }
28
+ pre { white-space: pre-wrap !important; }
29
+ `, Ut = 794, qt = Lt(
30
+ ({ url: _ }, yt) => {
31
+ const i = Ht(), vt = Dt(), Y = W(null), l = W(null), Z = W(1), [kt, K] = d(!0), [$, V] = d(null), [R, tt] = d([]), [w, T] = d(!1), [et, j] = d(""), [u, Nt] = d(!1), [E, Ct] = d(0), [I, Rt] = d(0), rt = W(!1);
32
+ rt.current = u;
33
+ const M = c((e, r) => {
34
+ r > 0 && (Z.current = r), Ct(Math.max(1, e + 1)), Rt(Z.current);
35
+ }, []), H = c(() => {
36
+ const e = l.current;
37
+ e && e.prev().catch(() => {
38
+ });
39
+ }, []), D = c(() => {
40
+ const e = l.current;
41
+ e && e.next().catch(() => {
42
+ });
43
+ }, []), X = c(() => T((e) => !e), []), G = c(() => {
44
+ const e = !rt.current;
45
+ Nt(e);
46
+ const r = l.current;
47
+ if (!r) return;
48
+ const t = r.renderer;
49
+ t && t.setAttribute("max-inline-size", e ? "9999" : "720");
50
+ }, []), O = W(/* @__PURE__ */ new Set()), p = c(() => {
51
+ O.current.forEach((e) => e());
52
+ }, []);
53
+ C(() => {
54
+ p();
55
+ }, [E, p]), C(() => {
56
+ p();
57
+ }, [I, p]), C(() => {
58
+ p();
59
+ }, [u, p]), C(() => {
60
+ p();
61
+ }, [R.length, p]);
62
+ const ot = c(() => [
63
+ {
64
+ items: [
65
+ { type: "button", icon: /* @__PURE__ */ o(Ft, { className: "rfp-w-4 rfp-h-4" }), tooltip: i("toolbar.toc"), action: X, disabled: R.length === 0, active: w }
66
+ ]
67
+ },
68
+ {
69
+ items: [
70
+ { type: "button", icon: /* @__PURE__ */ o(Wt, { className: "rfp-w-4 rfp-h-4" }), tooltip: i("toolbar.prev_page"), action: H, disabled: E <= 1 },
71
+ { type: "text", content: `${E} / ${I}`, minWidth: "4rem" },
72
+ { type: "button", icon: /* @__PURE__ */ o(_t, { className: "rfp-w-4 rfp-h-4" }), tooltip: i("toolbar.next_page"), action: D, disabled: E >= I }
73
+ ]
74
+ },
75
+ {
76
+ items: [
77
+ { type: "button", icon: u ? /* @__PURE__ */ o($t, { className: "rfp-w-4 rfp-h-4" }) : /* @__PURE__ */ o(jt, { className: "rfp-w-4 rfp-h-4" }), tooltip: i(u ? "toolbar.normal_width" : "toolbar.full_width"), action: G, active: u }
78
+ ]
79
+ }
80
+ ], [E, I, u, w, R.length, i, H, D, X, G]), Tt = c((e) => {
81
+ var r;
82
+ j(e), T(!1), (r = l.current) == null || r.goTo(e).catch(() => {
83
+ });
84
+ }, []);
85
+ Pt(yt, () => ({
86
+ getToolbarGroups: ot,
87
+ onToolbarChange: (e) => (O.current.add(e), () => O.current.delete(e)),
88
+ prevPage: H,
89
+ nextPage: D,
90
+ toggleFullWidth: G,
91
+ toggleToc: X
92
+ }), [ot, H, D, G, X]), C(() => {
93
+ const e = (r) => {
94
+ var t;
95
+ (t = r.filename) != null && t.includes("paginator") && r.preventDefault();
96
+ };
97
+ return window.addEventListener("error", e), () => window.removeEventListener("error", e);
98
+ }, []), C(() => {
99
+ const e = Y.current;
100
+ if (!e || !_) return;
101
+ let r = !1, t = null, S = !1;
102
+ const m = /* @__PURE__ */ new Map(), U = async () => {
103
+ var h, b, z, at, st, it;
104
+ if (!r) {
105
+ K(!0), V(null), tt([]), T(!1), j(""), e.replaceChildren();
106
+ try {
107
+ t = document.createElement("foliate-view"), e.appendChild(t), l.current = t, t.addEventListener("relocate", (ft) => {
108
+ var pt, dt, ut, mt, ht, bt, gt, xt;
109
+ const a = ft.detail;
110
+ if (!a) return;
111
+ const f = l.current, ct = ((pt = f == null ? void 0 : f.book) == null ? void 0 : pt.sections.length) ?? 0, s = f == null ? void 0 : f.renderer, q = ((ut = (dt = s == null ? void 0 : s.getContents) == null ? void 0 : dt.call(s)[0]) == null ? void 0 : ut.index) ?? -1;
112
+ if (s && typeof s.page == "number" && typeof s.pages == "number" && s.pages > 2 && q >= 0) {
113
+ S = !0;
114
+ const x = s.pages - 2;
115
+ m.set(q, x);
116
+ let v = 0;
117
+ for (let N = 0; N < q; N++)
118
+ v += m.get(N) ?? 0;
119
+ const A = v + Math.min(x, Math.max(1, s.page)), L = (a.fraction ?? 0) >= 0.999;
120
+ let k;
121
+ if (ct === 1)
122
+ k = x;
123
+ else if (L)
124
+ k = A;
125
+ else {
126
+ const N = ((mt = f == null ? void 0 : f.book) == null ? void 0 : mt.sections) ?? [], wt = ((ht = N[q]) == null ? void 0 : ht.size) ?? 0, zt = wt > 0 ? x / wt : 0;
127
+ let Q = 0;
128
+ for (let P = 0; P < ct; P++)
129
+ if (m.has(P))
130
+ Q += m.get(P);
131
+ else {
132
+ const At = ((bt = N[P]) == null ? void 0 : bt.size) ?? 0;
133
+ Q += Math.max(1, Math.round(At * zt));
134
+ }
135
+ k = Math.max(A, Q);
136
+ }
137
+ M(A - 1, k);
138
+ const J = a.tocItem;
139
+ J != null && J.href && j(J.href);
140
+ return;
141
+ }
142
+ const y = a.location;
143
+ if (y && typeof y.current == "number" && typeof y.total == "number") {
144
+ S = !0;
145
+ const v = (a.fraction ?? 0) >= 0.999 ? y.current + 1 : y.total;
146
+ M(y.current, v);
147
+ } else {
148
+ const x = ((xt = (gt = l.current) == null ? void 0 : gt.book) == null ? void 0 : xt.sections) ?? [], v = a.index ?? 0, A = a.fraction ?? 0, L = Math.max(x.length, 1), k = Math.round((v + A) / L * L);
149
+ M(k, L);
150
+ }
151
+ const B = a.tocItem;
152
+ B != null && B.href && j(B.href);
153
+ });
154
+ const g = await vt(_);
155
+ if (r) return;
156
+ if (!g.ok) throw new Error(`请求失败: ${g.status}`);
157
+ const Mt = await g.blob();
158
+ if (r) return;
159
+ let lt = "book.mobi";
160
+ try {
161
+ const a = new URL(_, window.location.href).pathname.split("/").pop();
162
+ a && (lt = decodeURIComponent(a));
163
+ } catch {
164
+ }
165
+ const St = new File([Mt], lt);
166
+ if (await t.open(St), r) {
167
+ (b = (h = t.book) == null ? void 0 : h.destroy) == null || b.call(h);
168
+ return;
169
+ }
170
+ const n = t.renderer;
171
+ if (n && (n.setAttribute("animated", ""), n.setAttribute("max-inline-size", "720"), n.setAttribute("margin", "48"), n.setAttribute("gap", "5%"), await ((z = n.next) == null ? void 0 : z.call(n)), (at = n.setStyles) == null || at.call(n, Gt)), r) return;
172
+ tt(((st = t.book) == null ? void 0 : st.toc) ?? []), K(!1), S || M(0, ((it = t.book) == null ? void 0 : it.sections.length) ?? 1);
173
+ } catch (g) {
174
+ console.warn("[MobiRenderer] Failed to load ebook:", g instanceof Error ? g.message : String(g)), r || (V(i("mobi.load_failed")), K(!1));
175
+ }
176
+ }
177
+ };
178
+ return Promise.resolve().then(U), () => {
179
+ var h, b, z;
180
+ r = !0;
181
+ try {
182
+ (h = t == null ? void 0 : t.close) == null || h.call(t);
183
+ } catch {
184
+ }
185
+ try {
186
+ (z = (b = t == null ? void 0 : t.book) == null ? void 0 : b.destroy) == null || z.call(b);
187
+ } catch {
188
+ }
189
+ if (t && t.parentNode === e)
190
+ try {
191
+ e.removeChild(t);
192
+ } catch {
193
+ }
194
+ l.current === t && (l.current = null);
195
+ };
196
+ }, [_, M, i]);
197
+ const Et = c(
198
+ (e) => !!e && e === et,
199
+ [et]
200
+ ), nt = (e, r = 0) => /* @__PURE__ */ o("ul", { style: { listStyle: "none", padding: 0, margin: r > 0 ? "0 0 0 16px" : 0 }, children: e.map((t, S) => {
201
+ var m, U;
202
+ return /* @__PURE__ */ F("li", { children: [
203
+ t.href ? /* @__PURE__ */ o(
204
+ "button",
205
+ {
206
+ onClick: () => Tt(t.href),
207
+ className: `rfp-w-full rfp-text-left rfp-py-2 rfp-px-3 rfp-text-sm rfp-rounded rfp-transition-all rfp-truncate ${Et(t.href) ? "rfp-text-fg-primary rfp-bg-surface-3 rfp-font-medium" : "rfp-text-fg-secondary hover:rfp-text-fg-primary hover:rfp-bg-surface-2"}`,
208
+ title: t.label,
209
+ children: (m = t.label) == null ? void 0 : m.trim()
210
+ }
211
+ ) : /* @__PURE__ */ o("div", { className: "rfp-w-full rfp-py-2 rfp-px-3 rfp-text-sm rfp-text-fg-tertiary rfp-truncate", children: (U = t.label) == null ? void 0 : U.trim() }),
212
+ t.subitems && t.subitems.length > 0 && nt(t.subitems, r + 1)
213
+ ] }, `${t.href ?? t.label}-${S}`);
214
+ }) });
215
+ return /* @__PURE__ */ F("div", { className: "rfp-relative rfp-w-full rfp-h-full rfp-flex rfp-justify-center rfp-bg-surface-1 rfp-overflow-hidden", children: [
216
+ $ && /* @__PURE__ */ o(Xt, { message: $ }),
217
+ kt && !$ && /* @__PURE__ */ o("div", { className: "rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-z-10", 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" }) }),
218
+ R.length > 0 && /* @__PURE__ */ F(
219
+ "div",
220
+ {
221
+ className: "rfp-absolute rfp-inset-0 rfp-z-20 rfp-flex rfp-transition-opacity rfp-duration-300",
222
+ style: { opacity: w ? 1 : 0, pointerEvents: w ? "auto" : "none" },
223
+ children: [
224
+ /* @__PURE__ */ F(
225
+ "div",
226
+ {
227
+ 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",
228
+ style: { transform: w ? "translateX(0)" : "translateX(-100%)" },
229
+ children: [
230
+ /* @__PURE__ */ F("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", children: [
231
+ /* @__PURE__ */ o("span", { className: "rfp-text-fg-primary rfp-font-medium rfp-text-sm", children: i("toolbar.toc") }),
232
+ /* @__PURE__ */ o(
233
+ "button",
234
+ {
235
+ onClick: () => T(!1),
236
+ className: "rfp-text-fg-tertiary hover:rfp-text-fg-primary rfp-transition-colors",
237
+ children: /* @__PURE__ */ o(It, { className: "rfp-w-4 rfp-h-4" })
238
+ }
239
+ )
240
+ ] }),
241
+ /* @__PURE__ */ o("div", { className: "rfp-flex-1 rfp-overflow-y-auto rfp-py-4 rfp-px-1", children: nt(R) })
242
+ ]
243
+ }
244
+ ),
245
+ /* @__PURE__ */ o(
246
+ "div",
247
+ {
248
+ className: "rfp-flex-1 rfp-transition-opacity rfp-duration-300",
249
+ style: { background: w ? "rgba(0,0,0,0.3)" : "transparent" },
250
+ onClick: () => T(!1)
251
+ }
252
+ )
253
+ ]
254
+ }
255
+ ),
256
+ !$ && /* @__PURE__ */ o(
257
+ "div",
258
+ {
259
+ ref: Y,
260
+ className: "rfp-h-full rfp-bg-surface-toolbar rfp-shadow-lg",
261
+ style: {
262
+ width: u ? "100%" : `${Ut}px`,
263
+ maxWidth: "100%",
264
+ transition: "width 0.3s ease"
265
+ }
266
+ }
267
+ )
268
+ ] });
269
+ }
270
+ );
271
+ qt.displayName = "MobiRenderer";
272
+ export {
273
+ qt as MobiRenderer
274
+ };
275
+ //# sourceMappingURL=index-fQGAUFAX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-fQGAUFAX.mjs","sources":["../../src/renderers/Mobi/index.tsx"],"sourcesContent":["import {\n useEffect,\n useRef,\n useState,\n useCallback,\n useImperativeHandle,\n forwardRef,\n} from 'react';\nimport { X, ChevronLeft, ChevronRight, Maximize2, Minimize2, List } from 'lucide-react';\nimport 'foliate-js/view.js';\nimport type { FoliateView, TocItem } from 'foliate-js/view.js';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\nimport type { ToolbarGroup } from '../toolbar.types';\n\nconst READER_CSS = `\n @namespace epub \"http://www.idpf.org/2007/ops\";\n html { color-scheme: light; }\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 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, li, blockquote, dd { line-height: 2; text-align: justify; }\n p { text-indent: 2em; margin: 0.8em 0; }\n h1 { text-align: center; margin: 1.5em 0 1em; }\n h2 { margin: 1.2em 0 0.8em; }\n h3 { margin: 1em 0 0.6em; }\n img { max-width: 100% !important; height: auto !important; }\n a { color: #2563eb; text-decoration: none; }\n pre { white-space: pre-wrap !important; }\n`;\n\nconst A4_WIDTH = 794;\n\nexport interface MobiRendererHandle extends RendererHandle {\n prevPage: () => void;\n nextPage: () => void;\n toggleFullWidth: () => void;\n toggleToc: () => void;\n}\n\ninterface MobiRendererProps {\n url: string;\n}\n\nexport const MobiRenderer = forwardRef<MobiRendererHandle, MobiRendererProps>(\n ({ url }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const hostRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<FoliateView | null>(null);\n\n // 模拟 epub.js 的 locations 显示\n const totalLocationsRef = useRef(1);\n\n // 内部状态管理\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [toc, setToc] = useState<TocItem[]>([]);\n const [showToc, setShowToc] = useState(false);\n const [activeTocHref, setActiveTocHref] = useState<string>('');\n const [isFullWidth, setIsFullWidth] = useState(false);\n const [currentChapter, setCurrentChapter] = useState(0);\n const [totalChapters, setTotalChapters] = useState(0);\n const isFullWidthRef = useRef(false);\n isFullWidthRef.current = isFullWidth;\n\n const reportProgress = useCallback((current: number, total: number) => {\n if (total > 0) totalLocationsRef.current = total;\n setCurrentChapter(Math.max(1, current + 1));\n setTotalChapters(totalLocationsRef.current);\n }, []);\n\n const handlePrev = useCallback(() => {\n const view = viewRef.current;\n if (!view) return;\n view.prev().catch(() => {});\n }, []);\n\n const handleNext = useCallback(() => {\n const view = viewRef.current;\n if (!view) return;\n view.next().catch(() => {});\n }, []);\n\n const toggleToc = useCallback(() => setShowToc((prev) => !prev), []);\n\n const toggleFullWidth = useCallback(() => {\n const newVal = !isFullWidthRef.current;\n setIsFullWidth(newVal);\n // 宽度改变后 paginator 需要重新分页\n const view = viewRef.current;\n if (!view) return;\n const renderer = (view as unknown as { renderer?: HTMLElement }).renderer;\n if (renderer) {\n renderer.setAttribute('max-inline-size', newVal ? '9999' : '720');\n }\n }, []);\n\n // 事件发射器:用于通知主组件工具栏状态变化\n const listenersRef = useRef<Set<() => void>>(new Set());\n const notifyToolbarChange = useCallback(() => {\n listenersRef.current.forEach(listener => listener());\n }, []);\n\n // 监听影响工具栏的状态变化\n useEffect(() => {\n notifyToolbarChange();\n }, [currentChapter, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [totalChapters, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [isFullWidth, notifyToolbarChange]);\n\n useEffect(() => {\n notifyToolbarChange();\n }, [toc.length, notifyToolbarChange]);\n\n // 工具栏配置\n const getToolbarGroups = useCallback((): ToolbarGroup[] => [\n {\n items: [\n { type: 'button', icon: <List className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.toc'), action: toggleToc, disabled: toc.length === 0, active: showToc },\n ],\n },\n {\n items: [\n { type: 'button', icon: <ChevronLeft className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.prev_page'), action: handlePrev, disabled: currentChapter <= 1 },\n { type: 'text', content: `${currentChapter} / ${totalChapters}`, minWidth: '4rem' },\n { type: 'button', icon: <ChevronRight className=\"rfp-w-4 rfp-h-4\" />, tooltip: t('toolbar.next_page'), action: handleNext, disabled: currentChapter >= totalChapters },\n ],\n },\n {\n items: [\n { type: 'button', icon: isFullWidth ? <Minimize2 className=\"rfp-w-4 rfp-h-4\" /> : <Maximize2 className=\"rfp-w-4 rfp-h-4\" />, tooltip: isFullWidth ? t('toolbar.normal_width') : t('toolbar.full_width'), action: toggleFullWidth, active: isFullWidth },\n ],\n },\n ], [currentChapter, totalChapters, isFullWidth, showToc, toc.length, t, handlePrev, handleNext, toggleToc, toggleFullWidth]);\n\n const handleTocClick = useCallback((href: string) => {\n setActiveTocHref(href);\n setShowToc(false);\n viewRef.current?.goTo(href).catch(() => {});\n }, []);\n\n useImperativeHandle(ref, () => ({\n getToolbarGroups,\n onToolbarChange: (listener: () => void) => {\n listenersRef.current.add(listener);\n return () => listenersRef.current.delete(listener);\n },\n prevPage: handlePrev,\n nextPage: handleNext,\n toggleFullWidth,\n toggleToc,\n }), [getToolbarGroups, handlePrev, handleNext, toggleFullWidth, toggleToc]);\n\n // 吞掉 foliate-js paginator 卸载/切换窗口期由 ResizeObserver 触发的 uncaught error。\n // 上游 bug:Paginator.destroy 里 unobserve 目标错了(unobserve(this) 而非 unobserve(container)),\n // observer 从未真正解除,view 已经半 destroy 时仍会触发一次 render,此时 #view / iframe body 已 null。\n // 已知触发:\n // - \"Cannot destructure property 'style' of 'el' as it is null\" (setStylesImportant)\n // - \"Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'\" (#replaceBackground)\n useEffect(() => {\n const handler = (e: ErrorEvent) => {\n if (e.filename?.includes('paginator')) {\n e.preventDefault();\n }\n };\n window.addEventListener('error', handler);\n return () => window.removeEventListener('error', handler);\n }, []);\n\n useEffect(() => {\n const host = hostRef.current;\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!host || !url) return;\n\n let cancelled = false;\n let view: FoliateView | null = null;\n let progressReported = false;\n // 多 section 文件的页码累加器:记录各 section 的实际页数\n const sectionPagesMap = new Map<number, number>();\n\n const load = async () => {\n if (cancelled) return;\n\n setLoading(true);\n setError(null);\n setToc([]);\n setShowToc(false);\n setActiveTocHref('');\n host.replaceChildren();\n\n try {\n view = document.createElement('foliate-view') as FoliateView;\n host.appendChild(view);\n viewRef.current = view;\n\n // 先注册事件\n view.addEventListener('relocate', (e: Event) => {\n const detail = (e as CustomEvent).detail;\n if (!detail) return;\n\n const currentView = viewRef.current;\n const sectionCount = currentView?.book?.sections.length ?? 0;\n const renderer = (currentView as unknown as {\n renderer?: {\n page?: number;\n pages?: number;\n getContents?: () => Array<{ index: number }>;\n };\n } | null)?.renderer;\n\n // 用 Paginator 的 page/pages 得到精确翻页数:\n // - 单 section:pages - 2 就是全书总页数\n // - 多 section:记录已翻过的 section 的 pages,累加得到全书页码\n const sectionIdx = renderer?.getContents?.()[0]?.index ?? -1;\n if (\n renderer\n && typeof renderer.page === 'number'\n && typeof renderer.pages === 'number'\n && renderer.pages > 2\n && sectionIdx >= 0\n ) {\n progressReported = true;\n const curSectionPages = renderer.pages - 2;\n // 更新当前 section 的实际页数(每次进入该 section 都刷新,防止首次未 render 完整)\n sectionPagesMap.set(sectionIdx, curSectionPages);\n\n // 累加已确知的前置 section pages\n let pagesBefore = 0;\n for (let i = 0; i < sectionIdx; i++) {\n pagesBefore += sectionPagesMap.get(i) ?? 0;\n }\n const currentPage = pagesBefore + Math.min(curSectionPages, Math.max(1, renderer.page));\n\n // total 策略:\n // - 单 section:pages - 2 就是全书精确页数\n // - 多 section:用\"当前 section 字符/页数比\"外推未访问 section 的 pages。\n // 同一本书字体、行距、页宽恒定,比率稳定,比 SectionProgress 字符估算准得多。\n // 翻到末页(fraction ≈ 1)时用 currentPage 覆盖,得到真实总数。\n const atEnd = (detail.fraction ?? 0) >= 0.999;\n let total: number;\n if (sectionCount === 1) {\n total = curSectionPages;\n } else if (atEnd) {\n total = currentPage;\n } else {\n const sections = currentView?.book?.sections ?? [];\n const curSize = (sections[sectionIdx] as { size?: number } | undefined)?.size ?? 0;\n const ratio = curSize > 0 ? curSectionPages / curSize : 0;\n let est = 0;\n for (let i = 0; i < sectionCount; i++) {\n if (sectionPagesMap.has(i)) {\n est += sectionPagesMap.get(i)!;\n } else {\n const s = (sections[i] as { size?: number } | undefined)?.size ?? 0;\n est += Math.max(1, Math.round(s * ratio));\n }\n }\n total = Math.max(currentPage, est);\n }\n\n reportProgress(currentPage - 1, total);\n const tocItem = detail.tocItem as { href?: string } | undefined;\n if (tocItem?.href) setActiveTocHref(tocItem.href);\n return;\n }\n\n // 兜底:SectionProgress.location(基于字符数估算)\n const loc = detail.location as { current?: number; total?: number } | undefined;\n if (loc && typeof loc.current === 'number' && typeof loc.total === 'number') {\n progressReported = true;\n // 当翻到末尾时(fraction 达到 1 表示全书 100%),用 current + 1 作为实际可达的 total,\n // 覆盖 SectionProgress 基于字符数向上取整的估算值(会高估)\n const atEnd = (detail.fraction ?? 0) >= 0.999;\n const actualTotal = atEnd ? loc.current + 1 : loc.total;\n reportProgress(loc.current, actualTotal);\n } else {\n // fallback:用 section 级别估算\n const sections = viewRef.current?.book?.sections ?? [];\n const idx = detail.index ?? 0;\n const frac = detail.fraction ?? 0;\n const total = Math.max(sections.length, 1);\n const current = Math.round((idx + frac) / total * total);\n reportProgress(current, total);\n }\n const tocItem = detail.tocItem as { href?: string } | undefined;\n if (tocItem?.href) {\n setActiveTocHref(tocItem.href);\n }\n });\n\n const res = await fetcher(url);\n if (cancelled) return;\n if (!res.ok) throw new Error(`请求失败: ${res.status}`);\n const blob = await res.blob();\n if (cancelled) return;\n let name = 'book.mobi';\n try {\n const u = new URL(url, window.location.href);\n const base = u.pathname.split('/').pop();\n if (base) name = decodeURIComponent(base);\n } catch { /* blob: URL */ }\n const file = new File([blob], name);\n\n await view.open(file);\n if (cancelled) { view.book?.destroy?.(); return; }\n\n // 配置 paginator:paginated 模式(默认),带动画\n const renderer = (view as unknown as { renderer: HTMLElement & {\n setStyles?: (css: string) => void;\n next?: () => Promise<void>;\n } }).renderer;\n\n if (renderer) {\n // flow=\"paginated\" 是默认值,不需要显式设置\n renderer.setAttribute('animated', '');\n renderer.setAttribute('max-inline-size', '720');\n renderer.setAttribute('margin', '48');\n renderer.setAttribute('gap', '5%');\n // 必须调 next() 渲染首页\n await renderer.next?.();\n // setStyles 依赖 view.document 存在,必须在 next() 触发首次渲染后调用\n renderer.setStyles?.(READER_CSS);\n }\n if (cancelled) return;\n\n setToc(view.book?.toc ?? []);\n setLoading(false);\n // 只在 relocate 事件从未报告 progress 时使用 sections.length 作为 fallback,\n // 避免覆盖 SectionProgress 报告的更准确的 total(通常在首页 render 时通过 relocate 已报告)\n if (!progressReported) {\n reportProgress(0, view.book?.sections.length ?? 1);\n }\n } catch (err) {\n // MOBI/EPUB 加载错误通常是文件损坏或 DRM 保护,用 warn 级别记录\n console.warn('[MobiRenderer] Failed to load ebook:', err instanceof Error ? err.message : String(err));\n if (!cancelled) {\n setError(t('mobi.load_failed'));\n setLoading(false);\n }\n }\n };\n\n // 延迟到 microtask 队列执行,让 StrictMode 的第一次 cleanup 有机会取消,\n // 避免两个并发的 view.open() 污染 foliate-js MOBI 解析器内部状态\n Promise.resolve().then(load);\n\n return () => {\n cancelled = true;\n try { (view as unknown as { close?: () => void })?.close?.(); } catch { /* ignore */ }\n try { view?.book?.destroy?.(); } catch { /* ignore */ }\n if (view && view.parentNode === host) {\n try { host.removeChild(view); } catch { /* ignore */ }\n }\n if (viewRef.current === view) viewRef.current = null;\n };\n }, [url, reportProgress, t]);\n\n const isActive = useCallback(\n (href: string | undefined) => !!href && href === activeTocHref,\n [activeTocHref]\n );\n\n const renderTocItems = (items: TocItem[], depth = 0) => (\n <ul style={{ listStyle: 'none', padding: 0, margin: depth > 0 ? '0 0 0 16px' : 0 }}>\n {items.map((item, i) => (\n <li key={`${item.href ?? item.label}-${i}`}>\n {item.href ? (\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 ${\n isActive(item.href)\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 ) : (\n <div className=\"rfp-w-full rfp-py-2 rfp-px-3 rfp-text-sm rfp-text-fg-tertiary rfp-truncate\">\n {item.label?.trim()}\n </div>\n )}\n {item.subitems && item.subitems.length > 0 && renderTocItems(item.subitems, depth + 1)}\n </li>\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-surface-1 rfp-overflow-hidden\">\n {error && <RendererError message={error} />}\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={{ opacity: showToc ? 1 : 0, pointerEvents: showToc ? 'auto' : 'none' }}\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={hostRef}\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 }}\n />\n )}\n </div>\n );\n }\n);\n\nMobiRenderer.displayName = 'MobiRenderer';\n"],"names":["READER_CSS","A4_WIDTH","MobiRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","hostRef","useRef","viewRef","totalLocationsRef","loading","setLoading","useState","error","setError","toc","setToc","showToc","setShowToc","activeTocHref","setActiveTocHref","isFullWidth","setIsFullWidth","currentChapter","setCurrentChapter","totalChapters","setTotalChapters","isFullWidthRef","reportProgress","useCallback","current","total","handlePrev","view","handleNext","toggleToc","prev","toggleFullWidth","newVal","renderer","listenersRef","notifyToolbarChange","listener","useEffect","getToolbarGroups","List","jsx","ChevronLeft","ChevronRight","Minimize2","Maximize2","handleTocClick","href","_a","useImperativeHandle","handler","e","host","cancelled","progressReported","sectionPagesMap","load","detail","currentView","sectionCount","sectionIdx","curSectionPages","pagesBefore","i","currentPage","atEnd","sections","_d","curSize","_e","ratio","est","s","_f","tocItem","loc","actualTotal","_h","_g","idx","frac","res","blob","name","base","file","_b","_c","err","isActive","renderTocItems","items","depth","item","jsxs","RendererError","X"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { jsx as r, jsxs as t, Fragment as y } from "react/jsx-runtime";
2
- import { useState as d, useEffect as E, useMemo as k } from "react";
3
- import { u as F, a as R, T as S, P as n, E as T } from "./index-CEeKt7L3.mjs";
4
- import { R as _ } from "./RendererError-D5i8eSpN.mjs";
5
- const $ = {
1
+ import { jsx as r, jsxs as t, Fragment as E } from "react/jsx-runtime";
2
+ import { forwardRef as R, useState as m, useEffect as T, useMemo as k, useImperativeHandle as F } from "react";
3
+ import { u as S, a as _, T as $, P as o, z as j } from "./index-DreA69iU.mjs";
4
+ import { R as A } from "./RendererError-D5i8eSpN.mjs";
5
+ const L = {
6
6
  srt: "srt",
7
7
  vtt: "vtt",
8
8
  lrc: "lrc",
@@ -11,73 +11,75 @@ const $ = {
11
11
  ssa: "ssa",
12
12
  ttml: "ttml",
13
13
  dfxp: "ttml"
14
- }, j = (a) => {
15
- var f;
16
- const l = ((f = a.split(".").pop()) == null ? void 0 : f.toLowerCase()) || "";
17
- return $[l];
18
- }, P = ({ url: a, fileName: l }) => {
19
- const f = F(), b = R(), [o, h] = d(""), [v, m] = d(!0), [u, x] = d(null);
20
- E(() => {
14
+ }, z = (s) => {
15
+ var l;
16
+ const a = ((l = s.split(".").pop()) == null ? void 0 : l.toLowerCase()) || "";
17
+ return L[a];
18
+ }, B = R(({ url: s, fileName: a }, l) => {
19
+ const n = S(), h = _(), [i, v] = m(""), [w, u] = m(!0), [x, g] = m(null);
20
+ T(() => {
21
21
  const e = new AbortController();
22
22
  return (async () => {
23
23
  try {
24
- m(!0), x(null), h(await T(a, { fetcher: b, signal: e.signal }));
24
+ u(!0), g(null), v(await j(s, { fetcher: h, signal: e.signal }));
25
25
  } catch (p) {
26
26
  if (p.name === "AbortError") return;
27
- console.warn("[SubtitleRenderer] Failed to load subtitle:", p instanceof Error ? p.message : String(p)), x(f("subtitle.load_failed"));
27
+ console.warn("[SubtitleRenderer] Failed to load subtitle:", p instanceof Error ? p.message : String(p)), g(n("subtitle.load_failed"));
28
28
  } finally {
29
- m(!1);
29
+ u(!1);
30
30
  }
31
31
  })(), () => e.abort();
32
- }, [a]);
33
- const s = k(() => {
34
- if (!o) return null;
32
+ }, [s]);
33
+ const f = k(() => {
34
+ if (!i) return null;
35
35
  try {
36
- return S(o, j(l));
36
+ return $(i, z(a));
37
37
  } catch (e) {
38
38
  return console.warn("[SubtitleRenderer] Failed to parse subtitle:", e instanceof Error ? e.message : String(e)), null;
39
39
  }
40
- }, [o, l]);
41
- if (v)
40
+ }, [i, a]);
41
+ if (F(l, () => ({
42
+ getToolbarGroups: () => []
43
+ }), []), w)
42
44
  return /* @__PURE__ */ r("div", { className: "rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]", 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" }) });
43
- if (u || !s)
44
- return /* @__PURE__ */ r(_, { message: u || f("subtitle.parse_failed") });
45
- const i = s.format === "lrc" || s.format === "elrc", g = s.metadata ?? {}, w = i ? "group-hover:rfp-bg-violet-400" : "group-hover:rfp-bg-sky-400";
45
+ if (x || !f)
46
+ return /* @__PURE__ */ r(A, { message: x || n("subtitle.parse_failed") });
47
+ const d = f.format === "lrc" || f.format === "elrc", b = f.metadata ?? {}, N = d ? "group-hover:rfp-bg-violet-400" : "group-hover:rfp-bg-sky-400";
46
48
  return /* @__PURE__ */ t("div", { className: "rfp-relative rfp-w-full rfp-h-full rfp-bg-[#0f0f12]", children: [
47
49
  /* @__PURE__ */ r("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-px-4 rfp-pt-6 rfp-pb-16", children: /* @__PURE__ */ t("div", { className: "rfp-relative", children: [
48
50
  /* @__PURE__ */ r("div", { className: "rfp-absolute rfp-left-[5px] rfp-top-2 rfp-bottom-2 rfp-w-px rfp-bg-surface-1" }),
49
- /* @__PURE__ */ r("ol", { className: "rfp-space-y-5", children: s.cues.map((e, c) => /* @__PURE__ */ t("li", { className: "rfp-relative rfp-pl-6 rfp-group", children: [
51
+ /* @__PURE__ */ r("ol", { className: "rfp-space-y-5", children: f.cues.map((e, c) => /* @__PURE__ */ t("li", { className: "rfp-relative rfp-pl-6 rfp-group", children: [
50
52
  /* @__PURE__ */ r(
51
53
  "div",
52
54
  {
53
- className: `rfp-absolute rfp-left-0 rfp-top-[0.4rem] rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${w}`
55
+ className: `rfp-absolute rfp-left-0 rfp-top-[0.4rem] rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${N}`
54
56
  }
55
57
  ),
56
58
  /* @__PURE__ */ t("div", { className: "rfp-flex rfp-flex-wrap rfp-items-baseline rfp-gap-x-3 rfp-gap-y-1 rfp-mb-1.5", children: [
57
- /* @__PURE__ */ r("span", { className: "rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums", children: n(e.start) }),
59
+ /* @__PURE__ */ r("span", { className: "rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums", children: o(e.start) }),
58
60
  /* @__PURE__ */ r("span", { className: "rfp-text-[11px] rfp-text-fg-disabled", children: "→" }),
59
- /* @__PURE__ */ r("span", { className: "rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums", children: n(e.end) }),
61
+ /* @__PURE__ */ r("span", { className: "rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums", children: o(e.end) }),
60
62
  /* @__PURE__ */ t("span", { className: "rfp-text-[10px] rfp-font-mono rfp-text-fg-disabled rfp-tabular-nums", children: [
61
63
  "#",
62
64
  e.id ?? c + 1
63
65
  ] }),
64
66
  e.style && /* @__PURE__ */ r("span", { className: "rfp-text-[9px] rfp-uppercase rfp-tracking-widest rfp-text-fg-tertiary rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-bg-surface-1 rfp-border rfp-border-line-weak", children: e.style })
65
67
  ] }),
66
- e.words && e.words.length > 0 ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors", children: e.words.map((p, N) => /* @__PURE__ */ t(
68
+ e.words && e.words.length > 0 ? /* @__PURE__ */ r("div", { className: "rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors", children: e.words.map((p, y) => /* @__PURE__ */ t(
67
69
  "span",
68
70
  {
69
71
  className: "rfp-inline-flex rfp-flex-col rfp-items-start",
70
- title: n(p.start),
72
+ title: o(p.start),
71
73
  children: [
72
- /* @__PURE__ */ r("span", { className: "rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums", children: n(p.start).slice(3, 8) }),
74
+ /* @__PURE__ */ r("span", { className: "rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums", children: o(p.start).slice(3, 8) }),
73
75
  /* @__PURE__ */ r("span", { className: "rfp-leading-snug", children: p.text })
74
76
  ]
75
77
  },
76
- `w-${N}`
78
+ `w-${y}`
77
79
  )) }) : /* @__PURE__ */ r(
78
80
  "p",
79
81
  {
80
- className: `rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary rfp-min-h-[1.25rem] ${i ? "rfp-text-base rfp-font-medium" : "rfp-text-sm"}`,
82
+ className: `rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary rfp-min-h-[1.25rem] ${d ? "rfp-text-base rfp-font-medium" : "rfp-text-sm"}`,
81
83
  children: e.text
82
84
  }
83
85
  )
@@ -85,18 +87,18 @@ const $ = {
85
87
  ] }) }),
86
88
  /* @__PURE__ */ t("div", { className: "rfp-pointer-events-none rfp-absolute rfp-bottom-3 rfp-right-3 rfp-flex rfp-items-center rfp-gap-2 rfp-px-2.5 rfp-py-1 rfp-rounded-full rfp-bg-surface-nav rfp-backdrop-blur rfp-border rfp-border-line-weak rfp-text-[10px] rfp-text-fg-tertiary rfp-font-mono rfp-tabular-nums", children: [
87
89
  /* @__PURE__ */ t("span", { children: [
88
- s.cues.length,
90
+ f.cues.length,
89
91
  " ",
90
- f(i ? "subtitle.lines" : "subtitle.cues")
92
+ n(d ? "subtitle.lines" : "subtitle.cues")
91
93
  ] }),
92
- g.length && /* @__PURE__ */ t(y, { children: [
94
+ b.length && /* @__PURE__ */ t(E, { children: [
93
95
  /* @__PURE__ */ r("span", { className: "rfp-text-fg-disabled", children: "·" }),
94
- /* @__PURE__ */ r("span", { children: g.length })
96
+ /* @__PURE__ */ r("span", { children: b.length })
95
97
  ] })
96
98
  ] })
97
99
  ] });
98
- };
100
+ });
99
101
  export {
100
- P as SubtitleRenderer
102
+ B as SubtitleRenderer
101
103
  };
102
- //# sourceMappingURL=index-C_BJatqr.mjs.map
104
+ //# sourceMappingURL=index-fSw6Hl5e.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-fSw6Hl5e.mjs","sources":["../../src/renderers/Subtitle/index.tsx"],"sourcesContent":["import { useState, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport {\n parseSubtitle,\n formatSubtitleTime,\n fetchTextUtf8,\n type SubtitleParseResult,\n type SubtitleFormat,\n} from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface SubtitleRendererProps {\n url: string;\n fileName: string;\n}\n\nconst FORMAT_BY_EXT: Record<string, SubtitleFormat> = {\n srt: 'srt',\n vtt: 'vtt',\n lrc: 'lrc',\n elrc: 'elrc',\n ass: 'ass',\n ssa: 'ssa',\n ttml: 'ttml',\n dfxp: 'ttml',\n};\n\nconst getFormat = (fileName: string): SubtitleFormat | undefined => {\n const ext = fileName.split('.').pop()?.toLowerCase() || '';\n return FORMAT_BY_EXT[ext];\n};\n\nexport const SubtitleRenderer = forwardRef<RendererHandle, SubtitleRendererProps>(({ url, fileName }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [text, setText] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n const load = async () => {\n try {\n setLoading(true);\n setError(null);\n setText(await fetchTextUtf8(url, { fetcher, signal: controller.signal }));\n } catch (err: any) {\n if (err.name === 'AbortError') return;\n console.warn('[SubtitleRenderer] Failed to load subtitle:', err instanceof Error ? err.message : String(err));\n setError(t('subtitle.load_failed'));\n } finally {\n setLoading(false);\n }\n };\n load();\n return () => controller.abort();\n }, [url]);\n\n const parsed: SubtitleParseResult | null = useMemo(() => {\n if (!text) return null;\n try {\n return parseSubtitle(text, getFormat(fileName));\n } catch (err) {\n // 字幕解析失败通常是格式不支持或文件损坏,用 warn 级别记录\n console.warn('[SubtitleRenderer] Failed to parse subtitle:', err instanceof Error ? err.message : String(err));\n return null;\n }\n }, [text, fileName]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n if (loading) {\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\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 || !parsed) {\n return <RendererError message={error || t('subtitle.parse_failed')} />;\n }\n\n const isLyric = parsed.format === 'lrc' || parsed.format === 'elrc';\n const meta = parsed.metadata ?? {};\n const dotHover = isLyric ? 'group-hover:rfp-bg-violet-400' : 'group-hover:rfp-bg-sky-400';\n\n return (\n <div className=\"rfp-relative rfp-w-full rfp-h-full rfp-bg-[#0f0f12]\">\n {/* 内容滚动区 */}\n <div className=\"rfp-w-full rfp-h-full rfp-overflow-auto rfp-px-4 rfp-pt-6 rfp-pb-16\">\n <div className=\"rfp-relative\">\n {/* vertical line */}\n <div className=\"rfp-absolute rfp-left-[5px] rfp-top-2 rfp-bottom-2 rfp-w-px rfp-bg-surface-1\" />\n\n <ol className=\"rfp-space-y-5\">\n {parsed.cues.map((cue, i) => (\n <li key={`cue-${i}`} className=\"rfp-relative rfp-pl-6 rfp-group\">\n {/* dot */}\n <div\n className={`rfp-absolute rfp-left-0 rfp-top-[0.4rem] rfp-w-3 rfp-h-3 rfp-rounded-full rfp-bg-surface-3 rfp-border-2 rfp-border-[#0f0f12] rfp-transition-colors ${dotHover}`}\n />\n\n <div className=\"rfp-flex rfp-flex-wrap rfp-items-baseline rfp-gap-x-3 rfp-gap-y-1 rfp-mb-1.5\">\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.start)}\n </span>\n <span className=\"rfp-text-[11px] rfp-text-fg-disabled\">→</span>\n <span className=\"rfp-text-[11px] rfp-font-mono rfp-text-fg-muted rfp-tabular-nums\">\n {formatSubtitleTime(cue.end)}\n </span>\n <span className=\"rfp-text-[10px] rfp-font-mono rfp-text-fg-disabled rfp-tabular-nums\">\n #{cue.id ?? i + 1}\n </span>\n {cue.style && (\n <span className=\"rfp-text-[9px] rfp-uppercase rfp-tracking-widest rfp-text-fg-tertiary rfp-px-1.5 rfp-py-0.5 rfp-rounded rfp-bg-surface-1 rfp-border rfp-border-line-weak\">\n {cue.style}\n </span>\n )}\n </div>\n\n {cue.words && cue.words.length > 0 ? (\n <div className=\"rfp-flex rfp-flex-wrap rfp-gap-x-1.5 rfp-gap-y-1 rfp-text-base rfp-text-fg-primary rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors\">\n {cue.words.map((word, wi) => (\n <span\n key={`w-${wi}`}\n className=\"rfp-inline-flex rfp-flex-col rfp-items-start\"\n title={formatSubtitleTime(word.start)}\n >\n <span className=\"rfp-text-[9px] rfp-text-fg-disabled rfp-font-mono rfp-leading-none rfp-tabular-nums\">\n {formatSubtitleTime(word.start).slice(3, 8)}\n </span>\n <span className=\"rfp-leading-snug\">{word.text}</span>\n </span>\n ))}\n </div>\n ) : (\n <p\n className={`rfp-whitespace-pre-wrap rfp-break-words rfp-leading-relaxed group-hover:rfp-text-fg-primary rfp-transition-colors rfp-text-fg-primary rfp-min-h-[1.25rem] ${\n isLyric ? 'rfp-text-base rfp-font-medium' : 'rfp-text-sm'\n }`}\n >\n {cue.text}\n </p>\n )}\n </li>\n ))}\n </ol>\n </div>\n </div>\n\n {/* 底部状态栏 */}\n <div className=\"rfp-pointer-events-none rfp-absolute rfp-bottom-3 rfp-right-3 rfp-flex rfp-items-center rfp-gap-2 rfp-px-2.5 rfp-py-1 rfp-rounded-full rfp-bg-surface-nav rfp-backdrop-blur rfp-border rfp-border-line-weak rfp-text-[10px] rfp-text-fg-tertiary rfp-font-mono rfp-tabular-nums\">\n <span>{parsed.cues.length} {isLyric ? t('subtitle.lines') : t('subtitle.cues')}</span>\n {meta.length && (\n <>\n <span className=\"rfp-text-fg-disabled\">·</span>\n <span>{meta.length}</span>\n </>\n )}\n </div>\n </div>\n );\n});\n"],"names":["FORMAT_BY_EXT","getFormat","fileName","ext","_a","SubtitleRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","text","setText","useState","loading","setLoading","error","setError","useEffect","controller","fetchTextUtf8","err","parsed","useMemo","parseSubtitle","useImperativeHandle","jsx","RendererError","isLyric","meta","dotHover","jsxs","cue","i","formatSubtitleTime","word","wi","Fragment"],"mappings":"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"}