@eternalheart/react-file-preview 1.3.7 → 1.3.9

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 (85) hide show
  1. package/README.md +1 -1
  2. package/lib/FilePreviewContent.d.ts +12 -1
  3. package/lib/FilePreviewContent.d.ts.map +1 -1
  4. package/lib/FilePreviewEmbed.d.ts +9 -1
  5. package/lib/FilePreviewEmbed.d.ts.map +1 -1
  6. package/lib/FilePreviewModal.d.ts +9 -1
  7. package/lib/FilePreviewModal.d.ts.map +1 -1
  8. package/lib/RequestContext.d.ts +24 -0
  9. package/lib/RequestContext.d.ts.map +1 -0
  10. package/lib/chunks/{index-BIg3vHQf.mjs → index-B-H9HQiI.mjs} +35 -35
  11. package/lib/chunks/index-B-H9HQiI.mjs.map +1 -0
  12. package/lib/chunks/{index-DOMMMe9f.mjs → index-BGeyzo6u.mjs} +2 -2
  13. package/lib/chunks/{index-DOMMMe9f.mjs.map → index-BGeyzo6u.mjs.map} +1 -1
  14. package/lib/chunks/{index-zDEwNk3h.mjs → index-BNUiNUWa.mjs} +35 -35
  15. package/lib/chunks/index-BNUiNUWa.mjs.map +1 -0
  16. package/lib/chunks/{index-DTH1IvOG.mjs → index-BSD3w5eG.mjs} +72 -72
  17. package/lib/chunks/index-BSD3w5eG.mjs.map +1 -0
  18. package/lib/chunks/{index-D_8IHm6o.mjs → index-BcBe6KW7.mjs} +11 -10
  19. package/lib/chunks/index-BcBe6KW7.mjs.map +1 -0
  20. package/lib/chunks/index-BdYkTSTt.mjs +51 -0
  21. package/lib/chunks/index-BdYkTSTt.mjs.map +1 -0
  22. package/lib/chunks/{index-BWbuffRN.mjs → index-BqEuP_8r.mjs} +8 -8
  23. package/lib/chunks/index-BqEuP_8r.mjs.map +1 -0
  24. package/lib/chunks/{index-LNXbKjrI.mjs → index-Bv93wiEK.mjs} +812 -681
  25. package/lib/chunks/index-Bv93wiEK.mjs.map +1 -0
  26. package/lib/chunks/{index-xTq9b3vw.mjs → index-CKirCT35.mjs} +13 -13
  27. package/lib/chunks/index-CKirCT35.mjs.map +1 -0
  28. package/lib/chunks/{index-BOEtlHD3.mjs → index-CgV8T0G5.mjs} +53 -53
  29. package/lib/chunks/index-CgV8T0G5.mjs.map +1 -0
  30. package/lib/chunks/{index-DinKO2op.mjs → index-D8GtNeDn.mjs} +2 -2
  31. package/lib/chunks/{index-DinKO2op.mjs.map → index-D8GtNeDn.mjs.map} +1 -1
  32. package/lib/chunks/{index-CQABwGVP.mjs → index-DGuiWJr7.mjs} +18 -18
  33. package/lib/chunks/index-DGuiWJr7.mjs.map +1 -0
  34. package/lib/chunks/{index-Yp36heK8.mjs → index-DV5Jd7Qe.mjs} +31 -31
  35. package/lib/chunks/index-DV5Jd7Qe.mjs.map +1 -0
  36. package/lib/chunks/{index-qxvk-6P6.mjs → index-DdOEWhrk.mjs} +33 -33
  37. package/lib/chunks/index-DdOEWhrk.mjs.map +1 -0
  38. package/lib/chunks/{index-w0tt7Myw.mjs → index-DmepcY31.mjs} +2 -2
  39. package/lib/chunks/{index-w0tt7Myw.mjs.map → index-DmepcY31.mjs.map} +1 -1
  40. package/lib/chunks/index-U3w45GW8.mjs +299 -0
  41. package/lib/chunks/index-U3w45GW8.mjs.map +1 -0
  42. package/lib/chunks/{index-BsSx9pGx.mjs → index-r3q2xCCI.mjs} +37 -36
  43. package/lib/chunks/index-r3q2xCCI.mjs.map +1 -0
  44. package/lib/chunks/{index-BEolw_uv.mjs → index-zEVVgWCH.mjs} +2 -2
  45. package/lib/chunks/{index-BEolw_uv.mjs.map → index-zEVVgWCH.mjs.map} +1 -1
  46. package/lib/chunks/{useShikiHighlight-DtWg9b8y.mjs → useShikiHighlight-DzEAK0S7.mjs} +7 -7
  47. package/lib/chunks/{useShikiHighlight-DtWg9b8y.mjs.map → useShikiHighlight-DzEAK0S7.mjs.map} +1 -1
  48. package/lib/index.cjs +20 -33
  49. package/lib/index.cjs.map +1 -1
  50. package/lib/index.css +1 -1
  51. package/lib/index.mjs +7 -7
  52. package/lib/renderers/Csv/index.d.ts.map +1 -1
  53. package/lib/renderers/Docx/index.d.ts.map +1 -1
  54. package/lib/renderers/Epub/index.d.ts.map +1 -1
  55. package/lib/renderers/Json/index.d.ts.map +1 -1
  56. package/lib/renderers/Markdown/index.d.ts.map +1 -1
  57. package/lib/renderers/Mobi/index.d.ts.map +1 -1
  58. package/lib/renderers/Msg/index.d.ts.map +1 -1
  59. package/lib/renderers/Pptx/index.d.ts.map +1 -1
  60. package/lib/renderers/Subtitle/index.d.ts.map +1 -1
  61. package/lib/renderers/Text/index.d.ts.map +1 -1
  62. package/lib/renderers/Xlsx/index.d.ts.map +1 -1
  63. package/lib/renderers/Xml/index.d.ts.map +1 -1
  64. package/lib/renderers/Zip/index.d.ts.map +1 -1
  65. package/lib/types.d.ts +1 -1
  66. package/lib/types.d.ts.map +1 -1
  67. package/package.json +4 -4
  68. package/lib/chunks/index--zZy1XpK.mjs +0 -299
  69. package/lib/chunks/index--zZy1XpK.mjs.map +0 -1
  70. package/lib/chunks/index-B5tBeF0g.mjs +0 -51
  71. package/lib/chunks/index-B5tBeF0g.mjs.map +0 -1
  72. package/lib/chunks/index-BIg3vHQf.mjs.map +0 -1
  73. package/lib/chunks/index-BOEtlHD3.mjs.map +0 -1
  74. package/lib/chunks/index-BWbuffRN.mjs.map +0 -1
  75. package/lib/chunks/index-BsSx9pGx.mjs.map +0 -1
  76. package/lib/chunks/index-CQABwGVP.mjs.map +0 -1
  77. package/lib/chunks/index-DTH1IvOG.mjs.map +0 -1
  78. package/lib/chunks/index-D_8IHm6o.mjs.map +0 -1
  79. package/lib/chunks/index-LNXbKjrI.mjs.map +0 -1
  80. package/lib/chunks/index-Yp36heK8.mjs.map +0 -1
  81. package/lib/chunks/index-qxvk-6P6.mjs.map +0 -1
  82. package/lib/chunks/index-xTq9b3vw.mjs.map +0 -1
  83. package/lib/chunks/index-zDEwNk3h.mjs.map +0 -1
  84. package/lib/chunks/xspreadsheet-CyBXARuf.mjs +0 -5215
  85. package/lib/chunks/xspreadsheet-CyBXARuf.mjs.map +0 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # React File Preview [![npm version](https://img.shields.io/npm/v/@eternalheart/@eternalheart/react-file-preview.svg)](https://www.npmjs.com/package/@eternalheart/react-file-preview)[![license](https://img.shields.io/npm/l/@eternalheart/react-file-preview.svg)](https://github.com/wh131462/file-preview/blob/master/LICENSE)[![downloads](https://img.shields.io/npm/dm/@eternalheart/react-file-preview.svg)](https://www.npmjs.com/package/@eternalheart/react-file-preview)
1
+ # React File Preview [![npm version](https://img.shields.io/npm/v/@eternalheart/react-file-preview.svg)](https://www.npmjs.com/package/@eternalheart/react-file-preview)[![license](https://img.shields.io/npm/l/@eternalheart/react-file-preview.svg)](https://github.com/wh131462/file-preview/blob/master/LICENSE)[![downloads](https://img.shields.io/npm/dm/@eternalheart/react-file-preview.svg)](https://www.npmjs.com/package/@eternalheart/react-file-preview)
2
2
 
3
3
  English | [简体中文](./README.zh-CN.md)
4
4
 
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { type Locale, type Messages, type Theme } from '@eternalheart/file-preview-core';
3
3
  import { PreviewFileInput, CustomRenderer } from './types';
4
- import type { CustomRendererEventPayload } from '@eternalheart/file-preview-core';
4
+ import type { CustomRendererEventPayload, PreviewFile, RequestHandler, RequestInitFactory, ShouldFetchAsBlob } from '@eternalheart/file-preview-core';
5
5
  export interface FilePreviewContentProps {
6
6
  files: PreviewFileInput[];
7
7
  currentIndex: number;
@@ -23,6 +23,17 @@ export interface FilePreviewContentProps {
23
23
  theme?: Theme;
24
24
  /** 自定义渲染器派发的事件出口,载荷为 `{ name, payload, file }` */
25
25
  onCustomEvent?: (event: CustomRendererEventPayload) => void;
26
+ /** 自定义 RequestInit(或工厂函数):用于注入 Authorization 等鉴权头 */
27
+ requestInit?: RequestInitFactory;
28
+ /** 自定义请求处理器:完全接管库内 fetch;与 requestInit 同时存在时 handler 接收已合并的 init */
29
+ requestHandler?: RequestHandler;
30
+ /** 返回 true 时,对应文件会先经 fetcher 拉成 blob: URL 再喂给 image/video/audio/pdf 等 renderer */
31
+ shouldFetchAsBlob?: ShouldFetchAsBlob;
32
+ /**
33
+ * 自定义下载回调。提供后完全接管下载行为;
34
+ * 不提供时,库内默认通过 fetcher 拉成 Blob 触发下载(鉴权 URL 场景自动可用)。
35
+ */
36
+ onDownload?: (file: PreviewFile) => void | Promise<void>;
26
37
  }
27
38
  export declare const FilePreviewContent: React.FC<FilePreviewContentProps>;
28
39
  //# sourceMappingURL=FilePreviewContent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AA8BlF,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC7D;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA6hBhE,CAAC"}
1
+ {"version":3,"file":"FilePreviewContent.d.ts","sourceRoot":"","sources":["../src/FilePreviewContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAmB,KAAK,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAYzI,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAyB,MAAM,SAAS,CAAC;AAClF,OAAO,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAgCtJ,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC5D,qDAAqD;IACrD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,oEAAoE;IACpE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAWhE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { PreviewFileInput, CustomRenderer } from './types';
2
- import type { Locale, Messages, Theme, CustomRendererEventPayload } from '@eternalheart/file-preview-core';
2
+ import type { Locale, Messages, Theme, CustomRendererEventPayload, PreviewFile, RequestHandler, RequestInitFactory, ShouldFetchAsBlob } from '@eternalheart/file-preview-core';
3
3
  interface FilePreviewEmbedProps {
4
4
  files: PreviewFileInput[];
5
5
  currentIndex?: number;
@@ -21,6 +21,14 @@ interface FilePreviewEmbedProps {
21
21
  theme?: Theme;
22
22
  /** 自定义渲染器派发的事件出口 */
23
23
  onCustomEvent?: (event: CustomRendererEventPayload) => void;
24
+ /** 自定义 RequestInit(或工厂函数):注入 Authorization 等鉴权头 */
25
+ requestInit?: RequestInitFactory;
26
+ /** 自定义请求处理器:完全接管库内 fetch */
27
+ requestHandler?: RequestHandler;
28
+ /** 返回 true 时,对应文件先 fetcher→blob URL 后喂给 image/video/audio/pdf 等 renderer */
29
+ shouldFetchAsBlob?: ShouldFetchAsBlob;
30
+ /** 自定义下载回调;不传时库内默认通过 fetcher 拉 Blob 触发下载 */
31
+ onDownload?: (file: PreviewFile) => void | Promise<void>;
24
32
  }
25
33
  export declare const FilePreviewEmbed: React.FC<FilePreviewEmbedProps>;
26
34
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"FilePreviewEmbed.d.ts","sourceRoot":"","sources":["../src/FilePreviewEmbed.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE3G,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,oBAAoB;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC7D;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAqD5D,CAAC"}
1
+ {"version":3,"file":"FilePreviewEmbed.d.ts","sourceRoot":"","sources":["../src/FilePreviewEmbed.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE/K,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,oBAAoB;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC5D,mDAAmD;IACnD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,4BAA4B;IAC5B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA6D5D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { PreviewFileInput, CustomRenderer } from './types';
2
- import type { Locale, Messages, Theme, CustomRendererEventPayload } from '@eternalheart/file-preview-core';
2
+ import type { Locale, Messages, Theme, CustomRendererEventPayload, PreviewFile, RequestHandler, RequestInitFactory, ShouldFetchAsBlob } from '@eternalheart/file-preview-core';
3
3
  interface FilePreviewModalProps {
4
4
  files: PreviewFileInput[];
5
5
  currentIndex: number;
@@ -17,6 +17,14 @@ interface FilePreviewModalProps {
17
17
  theme?: Theme;
18
18
  /** 自定义渲染器派发的事件出口 */
19
19
  onCustomEvent?: (event: CustomRendererEventPayload) => void;
20
+ /** 自定义 RequestInit(或工厂函数):注入 Authorization 等鉴权头 */
21
+ requestInit?: RequestInitFactory;
22
+ /** 自定义请求处理器:完全接管库内 fetch */
23
+ requestHandler?: RequestHandler;
24
+ /** 返回 true 时,对应文件先 fetcher→blob URL 后喂给 image/video/audio/pdf 等 renderer */
25
+ shouldFetchAsBlob?: ShouldFetchAsBlob;
26
+ /** 自定义下载回调;不传时库内默认通过 fetcher 拉 Blob 触发下载 */
27
+ onDownload?: (file: PreviewFile) => void | Promise<void>;
20
28
  }
21
29
  export declare const FilePreviewModal: React.FC<FilePreviewModalProps>;
22
30
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../src/FilePreviewModal.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE3G,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,oBAAoB;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC7D;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwF5D,CAAC"}
1
+ {"version":3,"file":"FilePreviewModal.d.ts","sourceRoot":"","sources":["../src/FilePreviewModal.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,0BAA0B,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE/K,UAAU,qBAAqB;IAC7B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,oBAAoB;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC5D,mDAAmD;IACnD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,4BAA4B;IAC5B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAgG5D,CAAC"}
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { Fetcher, PreviewFile, RequestHandler, RequestInitFactory, ShouldFetchAsBlob } from '@eternalheart/file-preview-core';
3
+ export interface RequestContextValue {
4
+ fetcher: Fetcher;
5
+ shouldFetchAsBlob?: ShouldFetchAsBlob;
6
+ }
7
+ export interface RequestProviderProps {
8
+ requestInit?: RequestInitFactory;
9
+ requestHandler?: RequestHandler;
10
+ shouldFetchAsBlob?: ShouldFetchAsBlob;
11
+ children: React.ReactNode;
12
+ }
13
+ export declare const RequestProvider: React.FC<RequestProviderProps>;
14
+ export declare function useRequest(): RequestContextValue;
15
+ export declare function useFetcher(): Fetcher;
16
+ /**
17
+ * 解析 file 的可消费 URL:
18
+ * - 未配置 shouldFetchAsBlob 或返回 false:直接返回 file.url
19
+ * - 返回 true:用 fetcher 拉成 blob: URL,组件卸载或 file 变化时 revoke
20
+ *
21
+ * 期间返回空字符串(表示 "还没准备好"),调用方应避免空 URL 时挂载到 <img src> 等。
22
+ */
23
+ export declare function useResolvedUrl(file: PreviewFile | undefined): string;
24
+ //# sourceMappingURL=RequestContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../src/RequestContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,iCAAiC,CAAC;AAGzC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAQD,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgB1D,CAAC;AAEF,wBAAgB,UAAU,IAAI,mBAAmB,CAEhD;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAqDpE"}
@@ -1,8 +1,8 @@
1
1
  import { jsx as r, jsxs as s, Fragment as N } from "react/jsx-runtime";
2
2
  import { useMemo as j, useState as m, useEffect as v, useCallback as S } from "react";
3
3
  import { ChevronDown as L, ChevronRight as $ } from "lucide-react";
4
- import { u as w, a as C, h as O } from "./index-LNXbKjrI.mjs";
5
- const E = {
4
+ import { u as k, a as C, c as O, b as E } from "./index-Bv93wiEK.mjs";
5
+ const R = {
6
6
  key: "#9cdcfe",
7
7
  string: "#ce9178",
8
8
  number: "#b5cea8",
@@ -11,7 +11,7 @@ const E = {
11
11
  colon: "rgb(255 255 255 / 0.6)",
12
12
  collapsed: "rgb(255 255 255 / 0.4)",
13
13
  arrow: "rgb(255 255 255 / 0.5)"
14
- }, R = {
14
+ }, J = {
15
15
  key: "#005cc5",
16
16
  string: "#032f62",
17
17
  number: "#005cc5",
@@ -20,10 +20,10 @@ const E = {
20
20
  colon: "rgb(23 23 23 / 0.6)",
21
21
  collapsed: "rgb(23 23 23 / 0.45)",
22
22
  arrow: "rgb(23 23 23 / 0.55)"
23
- }, b = ({ keyName: e, value: n, depth: l, defaultExpanded: y, colors: t }) => {
24
- const i = w(), [c, a] = m(y), f = l * 20, d = S(() => a((o) => !o), []);
23
+ }, b = ({ keyName: e, value: n, depth: f, defaultExpanded: i, colors: t }) => {
24
+ const d = k(), [a, y] = m(i), p = f * 20, h = S(() => y((o) => !o), []);
25
25
  if (n == null || typeof n != "object")
26
- return /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${f}px` }, children: [
26
+ return /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${p}px` }, children: [
27
27
  /* @__PURE__ */ r("span", { className: "rfp-w-4 rfp-h-5 rfp-flex-shrink-0" }),
28
28
  e !== void 0 && /* @__PURE__ */ s("span", { className: "rfp-flex-shrink-0", style: { color: t.key }, children: [
29
29
  '"',
@@ -31,10 +31,10 @@ const E = {
31
31
  '"',
32
32
  /* @__PURE__ */ r("span", { style: { color: t.colon }, children: ": " })
33
33
  ] }),
34
- J(n, t)
34
+ A(n, t)
35
35
  ] });
36
- const p = Array.isArray(n), u = (p ? n : Object.entries(n)).length, k = p ? "[" : "{", x = p ? "]" : "}";
37
- return u === 0 ? /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${f}px` }, children: [
36
+ const l = Array.isArray(n), c = (l ? n : Object.entries(n)).length, g = l ? "[" : "{", u = l ? "]" : "}";
37
+ return c === 0 ? /* @__PURE__ */ s("div", { className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm", style: { paddingLeft: `${p}px` }, children: [
38
38
  /* @__PURE__ */ r("span", { className: "rfp-w-4 rfp-h-5 rfp-flex-shrink-0" }),
39
39
  e !== void 0 && /* @__PURE__ */ s("span", { className: "rfp-flex-shrink-0", style: { color: t.key }, children: [
40
40
  '"',
@@ -43,68 +43,68 @@ const E = {
43
43
  /* @__PURE__ */ r("span", { style: { color: t.colon }, children: ": " })
44
44
  ] }),
45
45
  /* @__PURE__ */ s("span", { style: { color: t.bracket }, children: [
46
- k,
47
- x
46
+ g,
47
+ u
48
48
  ] })
49
49
  ] }) : /* @__PURE__ */ s("div", { children: [
50
50
  /* @__PURE__ */ s(
51
51
  "div",
52
52
  {
53
53
  className: "rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm rfp-cursor-pointer hover:rfp-bg-surface-1 rfp-select-none",
54
- style: { paddingLeft: `${f}px` },
55
- onClick: d,
54
+ style: { paddingLeft: `${p}px` },
55
+ onClick: h,
56
56
  children: [
57
- /* @__PURE__ */ r("span", { className: "rfp-w-4 rfp-h-5 rfp-flex-shrink-0 rfp-flex rfp-items-center rfp-justify-center", style: { color: t.arrow }, children: c ? /* @__PURE__ */ r(L, { className: "rfp-w-3.5 rfp-h-3.5" }) : /* @__PURE__ */ r($, { className: "rfp-w-3.5 rfp-h-3.5" }) }),
57
+ /* @__PURE__ */ r("span", { className: "rfp-w-4 rfp-h-5 rfp-flex-shrink-0 rfp-flex rfp-items-center rfp-justify-center", style: { color: t.arrow }, children: a ? /* @__PURE__ */ r(L, { className: "rfp-w-3.5 rfp-h-3.5" }) : /* @__PURE__ */ r($, { className: "rfp-w-3.5 rfp-h-3.5" }) }),
58
58
  e !== void 0 && /* @__PURE__ */ s("span", { className: "rfp-flex-shrink-0", style: { color: t.key }, children: [
59
59
  '"',
60
60
  e,
61
61
  '"',
62
62
  /* @__PURE__ */ r("span", { style: { color: t.colon }, children: ": " })
63
63
  ] }),
64
- /* @__PURE__ */ r("span", { style: { color: t.bracket }, children: k }),
65
- !c && /* @__PURE__ */ s("span", { className: "rfp-ml-1", style: { color: t.collapsed }, children: [
66
- p ? `${u} ${i("json.items")}` : `${u} ${i("json.keys")}`,
64
+ /* @__PURE__ */ r("span", { style: { color: t.bracket }, children: g }),
65
+ !a && /* @__PURE__ */ s("span", { className: "rfp-ml-1", style: { color: t.collapsed }, children: [
66
+ l ? `${c} ${d("json.items")}` : `${c} ${d("json.keys")}`,
67
67
  /* @__PURE__ */ s("span", { style: { color: t.bracket }, children: [
68
68
  " ",
69
- x
69
+ u
70
70
  ] })
71
71
  ] })
72
72
  ]
73
73
  }
74
74
  ),
75
- c && /* @__PURE__ */ s(N, { children: [
76
- p ? n.map((o, g) => /* @__PURE__ */ r(b, { value: o, depth: l + 1, defaultExpanded: l < 1, colors: t }, g)) : Object.entries(n).map(([o, g]) => /* @__PURE__ */ r(b, { keyName: o, value: g, depth: l + 1, defaultExpanded: l < 1, colors: t }, o)),
77
- /* @__PURE__ */ r("div", { className: "rfp-font-mono rfp-text-sm rfp-py-px", style: { paddingLeft: `${f + 20}px`, color: t.bracket }, children: x })
75
+ a && /* @__PURE__ */ s(N, { children: [
76
+ l ? n.map((o, x) => /* @__PURE__ */ r(b, { value: o, depth: f + 1, defaultExpanded: f < 1, colors: t }, x)) : Object.entries(n).map(([o, x]) => /* @__PURE__ */ r(b, { keyName: o, value: x, depth: f + 1, defaultExpanded: f < 1, colors: t }, o)),
77
+ /* @__PURE__ */ r("div", { className: "rfp-font-mono rfp-text-sm rfp-py-px", style: { paddingLeft: `${p + 20}px`, color: t.bracket }, children: u })
78
78
  ] })
79
79
  ] });
80
80
  };
81
- function J(e, n) {
81
+ function A(e, n) {
82
82
  return e === null ? /* @__PURE__ */ r("span", { style: { color: n.keyword, fontStyle: "italic" }, children: "null" }) : e === void 0 ? /* @__PURE__ */ r("span", { style: { color: n.keyword, fontStyle: "italic" }, children: "undefined" }) : typeof e == "boolean" ? /* @__PURE__ */ r("span", { style: { color: n.keyword }, children: String(e) }) : typeof e == "number" ? /* @__PURE__ */ r("span", { style: { color: n.number }, children: String(e) }) : typeof e == "string" ? /* @__PURE__ */ s("span", { style: { color: n.string }, children: [
83
83
  '"',
84
84
  e,
85
85
  '"'
86
86
  ] }) : /* @__PURE__ */ r("span", { style: { color: n.bracket }, children: String(e) });
87
87
  }
88
- function A(e) {
89
- return e === "light" ? R : E;
88
+ function T(e) {
89
+ return e === "light" ? J : R;
90
90
  }
91
- const F = ({ url: e }) => {
92
- const n = w(), l = C(), y = j(() => A(l), [l]), [t, i] = m(null), [c, a] = m(!0), [f, d] = m(null);
91
+ const G = ({ url: e }) => {
92
+ const n = k(), f = C(), i = O(), t = j(() => T(i), [i]), [d, a] = m(null), [y, p] = m(!0), [h, l] = m(null);
93
93
  return v(() => {
94
94
  (async () => {
95
95
  try {
96
- a(!0), d(null);
97
- const h = await O(e);
98
- i(JSON.parse(h));
99
- } catch (h) {
100
- d(n("json.load_failed")), console.error(h);
96
+ p(!0), l(null);
97
+ const c = await E(e, { fetcher: f });
98
+ a(JSON.parse(c));
99
+ } catch (c) {
100
+ l(n("json.load_failed")), console.error(c);
101
101
  } finally {
102
- a(!1);
102
+ p(!1);
103
103
  }
104
104
  })();
105
- }, [e]), c ? /* @__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" }) }) : f ? /* @__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: f }) }) }) : /* @__PURE__ */ r("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4", children: /* @__PURE__ */ r(b, { value: t, depth: 0, defaultExpanded: !0, colors: y }) });
105
+ }, [e]), y ? /* @__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__ */ r("div", { className: "rfp-w-full rfp-h-full rfp-overflow-auto rfp-bg-code-bg rfp-py-3 rfp-pr-4", children: /* @__PURE__ */ r(b, { value: d, depth: 0, defaultExpanded: !0, colors: t }) });
106
106
  };
107
107
  export {
108
- F as JsonRenderer
108
+ G as JsonRenderer
109
109
  };
110
- //# sourceMappingURL=index-BIg3vHQf.mjs.map
110
+ //# sourceMappingURL=index-B-H9HQiI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-B-H9HQiI.mjs","sources":["../../src/renderers/Json/index.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { ChevronRight, ChevronDown } from 'lucide-react';\nimport { fetchTextUtf8 } from '@eternalheart/file-preview-core';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { useResolvedTheme, type ResolvedTheme } from '../../ThemeContext';\n\ninterface JsonRendererProps {\n url: string;\n fileName: string;\n}\n\ninterface JsonColors {\n key: string;\n string: string;\n number: string;\n keyword: string;\n bracket: string; // { } [ ]\n colon: string; // :\n collapsed: string; // \"N items / N keys\" 折叠提示\n arrow: string; // 折叠箭头\n}\n\n// VSCode Dark Plus / GitHub Light 两套配色,与 react-syntax-highlighter 的 vscDarkPlus / vs 主题保持一致\nconst DARK_COLORS: JsonColors = {\n key: '#9cdcfe',\n string: '#ce9178',\n number: '#b5cea8',\n keyword: '#569cd6',\n bracket: '#d4d4d4',\n colon: 'rgb(255 255 255 / 0.6)',\n collapsed: 'rgb(255 255 255 / 0.4)',\n arrow: 'rgb(255 255 255 / 0.5)',\n};\n\nconst LIGHT_COLORS: JsonColors = {\n key: '#005cc5',\n string: '#032f62',\n number: '#005cc5',\n keyword: '#d73a49',\n bracket: '#24292e',\n colon: 'rgb(23 23 23 / 0.6)',\n collapsed: 'rgb(23 23 23 / 0.45)',\n arrow: 'rgb(23 23 23 / 0.55)',\n};\n\n// ---------- JSON 树节点 ----------\n\ninterface JsonNodeProps {\n keyName?: string;\n value: unknown;\n depth: number;\n defaultExpanded: boolean;\n colors: JsonColors;\n}\n\nconst JsonNode: React.FC<JsonNodeProps> = ({ keyName, value, depth, defaultExpanded, colors }) => {\n const t = useTranslator();\n const [expanded, setExpanded] = useState(defaultExpanded);\n const indent = depth * 20;\n\n const toggle = useCallback(() => setExpanded(prev => !prev), []);\n\n // 基本类型\n if (value === null || value === undefined || typeof value !== 'object') {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n {renderPrimitive(value, colors)}\n </div>\n );\n }\n\n const isArray = Array.isArray(value);\n const entries = isArray ? (value as unknown[]) : Object.entries(value as Record<string, unknown>);\n const count = entries.length;\n const openBracket = isArray ? '[' : '{';\n const closeBracket = isArray ? ']' : '}';\n\n // 空对象/数组\n if (count === 0) {\n return (\n <div className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm\" style={{ paddingLeft: `${indent}px` }}>\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0\" />\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}{closeBracket}</span>\n </div>\n );\n }\n\n return (\n <div>\n {/* 折叠行 */}\n <div\n className=\"rfp-flex rfp-items-start rfp-py-px rfp-font-mono rfp-text-sm rfp-cursor-pointer hover:rfp-bg-surface-1 rfp-select-none\"\n style={{ paddingLeft: `${indent}px` }}\n onClick={toggle}\n >\n <span className=\"rfp-w-4 rfp-h-5 rfp-flex-shrink-0 rfp-flex rfp-items-center rfp-justify-center\" style={{ color: colors.arrow }}>\n {expanded\n ? <ChevronDown className=\"rfp-w-3.5 rfp-h-3.5\" />\n : <ChevronRight className=\"rfp-w-3.5 rfp-h-3.5\" />\n }\n </span>\n {keyName !== undefined && (\n <span className=\"rfp-flex-shrink-0\" style={{ color: colors.key }}>\n \"{keyName}\"<span style={{ color: colors.colon }}>: </span>\n </span>\n )}\n <span style={{ color: colors.bracket }}>{openBracket}</span>\n {!expanded && (\n <span className=\"rfp-ml-1\" style={{ color: colors.collapsed }}>\n {isArray ? `${count} ${t('json.items')}` : `${count} ${t('json.keys')}`}\n <span style={{ color: colors.bracket }}> {closeBracket}</span>\n </span>\n )}\n </div>\n\n {/* 子节点 */}\n {expanded && (\n <>\n {isArray\n ? (value as unknown[]).map((item, i) => (\n <JsonNode key={i} value={item} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n : Object.entries(value as Record<string, unknown>).map(([k, v]) => (\n <JsonNode key={k} keyName={k} value={v} depth={depth + 1} defaultExpanded={depth < 1} colors={colors} />\n ))\n }\n <div className=\"rfp-font-mono rfp-text-sm rfp-py-px\" style={{ paddingLeft: `${indent + 20}px`, color: colors.bracket }}>\n {closeBracket}\n </div>\n </>\n )}\n </div>\n );\n};\n\nfunction renderPrimitive(value: unknown, colors: JsonColors) {\n if (value === null) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>null</span>;\n if (value === undefined) return <span style={{ color: colors.keyword, fontStyle: 'italic' }}>undefined</span>;\n if (typeof value === 'boolean') return <span style={{ color: colors.keyword }}>{String(value)}</span>;\n if (typeof value === 'number') return <span style={{ color: colors.number }}>{String(value)}</span>;\n if (typeof value === 'string') return <span style={{ color: colors.string }}>\"{value}\"</span>;\n return <span style={{ color: colors.bracket }}>{String(value)}</span>;\n}\n\nfunction pickColors(theme: ResolvedTheme): JsonColors {\n return theme === 'light' ? LIGHT_COLORS : DARK_COLORS;\n}\n\n// ---------- Main ----------\n\nexport const JsonRenderer: React.FC<JsonRendererProps> = ({ url }) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const resolvedTheme = useResolvedTheme();\n const colors = useMemo(() => pickColors(resolvedTheme), [resolvedTheme]);\n const [data, setData] = useState<unknown>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const loadJson = async () => {\n try {\n setLoading(true);\n setError(null);\n const text = await fetchTextUtf8(url, { fetcher });\n setData(JSON.parse(text));\n } catch (err) {\n setError(t('json.load_failed'));\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n loadJson();\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 rfp-py-3 rfp-pr-4\">\n <JsonNode value={data} depth={0} defaultExpanded colors={colors} />\n </div>\n );\n};\n"],"names":["DARK_COLORS","LIGHT_COLORS","JsonNode","keyName","value","depth","defaultExpanded","colors","t","useTranslator","expanded","setExpanded","useState","indent","toggle","useCallback","prev","jsxs","jsx","renderPrimitive","isArray","count","openBracket","closeBracket","ChevronDown","ChevronRight","Fragment","item","i","k","v","pickColors","theme","JsonRenderer","url","fetcher","useFetcher","resolvedTheme","useResolvedTheme","useMemo","data","setData","loading","setLoading","error","setError","useEffect","text","fetchTextUtf8","err"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
2
  import { useState as u, useRef as v, useEffect as g } from "react";
3
3
  import x from "video.js";
4
- import { u as y } from "./index-LNXbKjrI.mjs";
4
+ import { u as y } from "./index-Bv93wiEK.mjs";
5
5
  const b = (r) => {
6
6
  var s;
7
7
  const o = ((s = r.split(".").pop()) == null ? void 0 : s.toLowerCase().split("?")[0]) || "";
@@ -93,4 +93,4 @@ const b = (r) => {
93
93
  export {
94
94
  L as VideoRenderer
95
95
  };
96
- //# sourceMappingURL=index-DOMMMe9f.mjs.map
96
+ //# sourceMappingURL=index-BGeyzo6u.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DOMMMe9f.mjs","sources":["../../src/renderers/Video/index.tsx"],"sourcesContent":["import { useRef, useEffect, useState } from 'react';\nimport videojs from 'video.js';\nimport 'video.js/dist/video-js.css';\nimport { useTranslator } from '../../i18n/LocaleContext';\n\ntype VideoJsPlayer = ReturnType<typeof videojs>;\n\ninterface VideoRendererProps {\n url: string;\n}\n\n// 根据 URL 获取视频 MIME 类型\nconst getVideoType = (url: string): string => {\n const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';\n const typeMap: Record<string, string> = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime', // MOV 使用 QuickTime MIME 类型\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/mp4',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n };\n return typeMap[ext] || 'video/mp4';\n};\n\nexport const VideoRenderer: React.FC<VideoRendererProps> = ({ url }) => {\n const t = useTranslator();\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const videoRef = useRef<HTMLDivElement>(null);\n const playerRef = useRef<VideoJsPlayer | null>(null);\n\n useEffect(() => {\n // 确保 Video.js 播放器只初始化一次\n if (!playerRef.current && videoRef.current) {\n const videoElement = document.createElement('video-js');\n videoElement.classList.add('vjs-big-play-centered', 'vjs-theme-apple');\n videoRef.current.appendChild(videoElement);\n\n const videoType = getVideoType(url);\n\n // 为 MOV 格式提供多个 MIME 类型作为备用\n const sources = videoType === 'video/quicktime'\n ? [\n { src: url, type: 'video/quicktime' },\n { src: url, type: 'video/mp4' } // 备用方案\n ]\n : [{ src: url, type: videoType }];\n\n const player = videojs(videoElement, {\n controls: true,\n fill: true,\n preload: 'auto',\n controlBar: {\n children: [\n 'playToggle',\n 'volumePanel',\n 'currentTimeDisplay',\n 'timeDivider',\n 'durationDisplay',\n 'progressControl',\n 'remainingTimeDisplay',\n 'fullscreenToggle'\n ],\n volumePanel: {\n inline: false\n }\n },\n html5: {\n vhs: {\n overrideNative: true\n },\n nativeVideoTracks: false,\n nativeAudioTracks: false,\n nativeTextTracks: false\n },\n sources\n });\n\n // 确保视频保持比例\n const videoEl = player.el().querySelector('video');\n if (videoEl) {\n (videoEl as HTMLVideoElement).style.objectFit = 'contain';\n }\n\n // 监听加载完成\n player.on('loadeddata', () => {\n setIsLoading(false);\n });\n\n player.on('error', () => {\n const error = player.error();\n console.error('Video.js error:', error);\n setError(t('video.load_failed_with_error', { error: error?.message || t('common.unknown_error') }));\n setIsLoading(false);\n });\n\n playerRef.current = player;\n }\n }, [url]);\n\n // 清理函数\n useEffect(() => {\n const player = playerRef.current;\n\n return () => {\n if (player && !player.isDisposed()) {\n player.dispose();\n playerRef.current = null;\n }\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-center\">\n <div className=\"rfp-w-16 rfp-h-16 rfp-mx-auto rfp-mb-4 rfp-rounded-full rfp-bg-red-500/10 rfp-flex rfp-items-center rfp-justify-center\">\n <svg className=\"rfp-w-8 rfp-h-8 rfp-text-red-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n </div>\n <p className=\"rfp-text-lg rfp-font-medium rfp-text-fg-primary rfp-mb-2\">{t('video.load_failed')}</p>\n <p className=\"rfp-text-sm rfp-text-fg-tertiary\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-full rfp-h-full rfp-relative\">\n {/* 加载状态 */}\n {isLoading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-3 rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-3 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('video.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 视频播放器容器 */}\n <div\n ref={videoRef}\n className=\"rfp-overflow-hidden rfp-w-full rfp-h-full [&_video]:rfp-object-contain\"\n style={{\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)'\n }}\n />\n </div>\n </div>\n );\n};\n"],"names":["getVideoType","url","ext","_a","VideoRenderer","t","useTranslator","error","setError","useState","isLoading","setIsLoading","videoRef","useRef","playerRef","useEffect","videoElement","videoType","player","videojs","videoEl","jsxs","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"index-BGeyzo6u.mjs","sources":["../../src/renderers/Video/index.tsx"],"sourcesContent":["import { useRef, useEffect, useState } from 'react';\nimport videojs from 'video.js';\nimport 'video.js/dist/video-js.css';\nimport { useTranslator } from '../../i18n/LocaleContext';\n\ntype VideoJsPlayer = ReturnType<typeof videojs>;\n\ninterface VideoRendererProps {\n url: string;\n}\n\n// 根据 URL 获取视频 MIME 类型\nconst getVideoType = (url: string): string => {\n const ext = url.split('.').pop()?.toLowerCase().split('?')[0] || '';\n const typeMap: Record<string, string> = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mov: 'video/quicktime', // MOV 使用 QuickTime MIME 类型\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n m4v: 'video/mp4',\n '3gp': 'video/3gpp',\n flv: 'video/x-flv',\n };\n return typeMap[ext] || 'video/mp4';\n};\n\nexport const VideoRenderer: React.FC<VideoRendererProps> = ({ url }) => {\n const t = useTranslator();\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const videoRef = useRef<HTMLDivElement>(null);\n const playerRef = useRef<VideoJsPlayer | null>(null);\n\n useEffect(() => {\n // 确保 Video.js 播放器只初始化一次\n if (!playerRef.current && videoRef.current) {\n const videoElement = document.createElement('video-js');\n videoElement.classList.add('vjs-big-play-centered', 'vjs-theme-apple');\n videoRef.current.appendChild(videoElement);\n\n const videoType = getVideoType(url);\n\n // 为 MOV 格式提供多个 MIME 类型作为备用\n const sources = videoType === 'video/quicktime'\n ? [\n { src: url, type: 'video/quicktime' },\n { src: url, type: 'video/mp4' } // 备用方案\n ]\n : [{ src: url, type: videoType }];\n\n const player = videojs(videoElement, {\n controls: true,\n fill: true,\n preload: 'auto',\n controlBar: {\n children: [\n 'playToggle',\n 'volumePanel',\n 'currentTimeDisplay',\n 'timeDivider',\n 'durationDisplay',\n 'progressControl',\n 'remainingTimeDisplay',\n 'fullscreenToggle'\n ],\n volumePanel: {\n inline: false\n }\n },\n html5: {\n vhs: {\n overrideNative: true\n },\n nativeVideoTracks: false,\n nativeAudioTracks: false,\n nativeTextTracks: false\n },\n sources\n });\n\n // 确保视频保持比例\n const videoEl = player.el().querySelector('video');\n if (videoEl) {\n (videoEl as HTMLVideoElement).style.objectFit = 'contain';\n }\n\n // 监听加载完成\n player.on('loadeddata', () => {\n setIsLoading(false);\n });\n\n player.on('error', () => {\n const error = player.error();\n console.error('Video.js error:', error);\n setError(t('video.load_failed_with_error', { error: error?.message || t('common.unknown_error') }));\n setIsLoading(false);\n });\n\n playerRef.current = player;\n }\n }, [url]);\n\n // 清理函数\n useEffect(() => {\n const player = playerRef.current;\n\n return () => {\n if (player && !player.isDisposed()) {\n player.dispose();\n playerRef.current = null;\n }\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-center\">\n <div className=\"rfp-w-16 rfp-h-16 rfp-mx-auto rfp-mb-4 rfp-rounded-full rfp-bg-red-500/10 rfp-flex rfp-items-center rfp-justify-center\">\n <svg className=\"rfp-w-8 rfp-h-8 rfp-text-red-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n </div>\n <p className=\"rfp-text-lg rfp-font-medium rfp-text-fg-primary rfp-mb-2\">{t('video.load_failed')}</p>\n <p className=\"rfp-text-sm rfp-text-fg-tertiary\">{error}</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"rfp-flex rfp-items-center rfp-justify-center rfp-w-full rfp-h-full\">\n <div className=\"rfp-w-full rfp-h-full rfp-relative\">\n {/* 加载状态 */}\n {isLoading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-3 rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-12 rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-3 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('video.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 视频播放器容器 */}\n <div\n ref={videoRef}\n className=\"rfp-overflow-hidden rfp-w-full rfp-h-full [&_video]:rfp-object-contain\"\n style={{\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05)'\n }}\n />\n </div>\n </div>\n );\n};\n"],"names":["getVideoType","url","ext","_a","VideoRenderer","t","useTranslator","error","setError","useState","isLoading","setIsLoading","videoRef","useRef","playerRef","useEffect","videoElement","videoType","player","videojs","videoEl","jsxs","jsx"],"mappings":"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"}
@@ -1,50 +1,50 @@
1
- import { jsx as r, jsxs as N } from "react/jsx-runtime";
2
- import { useState as f, useRef as A, useEffect as y, useCallback as G } from "react";
3
- import P from "mammoth";
4
- import { u as T } from "./index-LNXbKjrI.mjs";
5
- const _ = 1123, E = 60, v = 50, D = _ - E * 2, I = 24, w = {
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
6
  fontFamily: "system-ui, -apple-system, sans-serif",
7
7
  lineHeight: "1.8",
8
8
  color: "#333"
9
- }, L = ({ url: a }) => {
10
- const H = T(), [n, c] = f(""), [b, p] = f(!0), [d, u] = f(null), [h, m] = f([]), i = A(null);
11
- y(() => {
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
12
  (async () => {
13
- p(!0), u(null), c("");
13
+ d(!0), m(null), u("");
14
14
  try {
15
- const e = await fetch(a);
15
+ const e = await p(i);
16
16
  if (!e.ok)
17
17
  throw new Error("文件加载失败");
18
- const t = await e.arrayBuffer(), s = await P.convertToHtml({ arrayBuffer: t });
19
- c(s.value);
18
+ const t = await e.arrayBuffer(), s = await T.convertToHtml({ arrayBuffer: t });
19
+ u(s.value);
20
20
  } catch (e) {
21
- console.error("Docx 解析错误:", e), u(H("docx.parse_failed"));
21
+ console.error("Docx 解析错误:", e), m(c("docx.parse_failed"));
22
22
  } finally {
23
- p(!1);
23
+ d(!1);
24
24
  }
25
25
  })();
26
- }, [a]);
27
- const x = G(() => {
28
- const o = i.current;
26
+ }, [i, p, c]);
27
+ const y = P(() => {
28
+ const o = a.current;
29
29
  if (!o || !n) return;
30
30
  const e = Array.from(o.children);
31
31
  if (e.length === 0) {
32
- m([n]);
32
+ g([n]);
33
33
  return;
34
34
  }
35
35
  const t = [[]];
36
36
  let s = 0;
37
37
  for (const l of e) {
38
- const g = l.offsetHeight;
39
- s > 0 && s + g > D && (t.push([]), s = 0), t[t.length - 1].push(l.outerHTML), s += g;
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
40
  }
41
- t.length === 0 && t.push([]), m(t.map((l) => l.join("")));
41
+ t.length === 0 && t.push([]), g(t.map((l) => l.join("")));
42
42
  }, [n]);
43
- return y(() => {
44
- !n || !i.current || requestAnimationFrame(() => {
45
- x();
43
+ return w(() => {
44
+ !n || !a.current || requestAnimationFrame(() => {
45
+ y();
46
46
  });
47
- }, [n, x]), b ? /* @__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" }) }) : d ? /* @__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: d }) }) }) : /* @__PURE__ */ N(
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
48
  "div",
49
49
  {
50
50
  className: "rfp-w-full rfp-h-full rfp-overflow-auto",
@@ -53,13 +53,13 @@ const _ = 1123, E = 60, v = 50, D = _ - E * 2, I = 24, w = {
53
53
  /* @__PURE__ */ r(
54
54
  "div",
55
55
  {
56
- ref: i,
56
+ ref: a,
57
57
  dangerouslySetInnerHTML: { __html: n },
58
58
  style: {
59
- ...w,
59
+ ...E,
60
60
  position: "absolute",
61
61
  visibility: "hidden",
62
- width: `${794 - v * 2}px`,
62
+ width: `${794 - _ * 2}px`,
63
63
  pointerEvents: "none"
64
64
  }
65
65
  }
@@ -68,24 +68,24 @@ const _ = 1123, E = 60, v = 50, D = _ - E * 2, I = 24, w = {
68
68
  "div",
69
69
  {
70
70
  className: "rfp-py-6 md:rfp-py-10 rfp-flex rfp-flex-col rfp-items-center",
71
- style: { gap: `${I}px` },
72
- children: (h.length > 0 ? h : [""]).map((o, e) => /* @__PURE__ */ r(
71
+ style: { gap: `${j}px` },
72
+ children: (x.length > 0 ? x : [""]).map((o, e) => /* @__PURE__ */ r(
73
73
  "div",
74
74
  {
75
75
  style: {
76
76
  width: "100%",
77
77
  maxWidth: "794px",
78
- minHeight: `${_}px`,
78
+ minHeight: `${H}px`,
79
79
  background: "white",
80
80
  boxShadow: "0 2px 12px rgba(0, 0, 0, 0.15)",
81
81
  flexShrink: 0,
82
- padding: `${E}px ${v}px`
82
+ padding: `${b}px ${_}px`
83
83
  },
84
84
  children: /* @__PURE__ */ r(
85
85
  "div",
86
86
  {
87
87
  dangerouslySetInnerHTML: { __html: o },
88
- style: w
88
+ style: E
89
89
  }
90
90
  )
91
91
  },
@@ -98,6 +98,6 @@ const _ = 1123, E = 60, v = 50, D = _ - E * 2, I = 24, w = {
98
98
  );
99
99
  };
100
100
  export {
101
- L as DocxRenderer
101
+ M as DocxRenderer
102
102
  };
103
- //# sourceMappingURL=index-zDEwNk3h.mjs.map
103
+ //# sourceMappingURL=index-BNUiNUWa.mjs.map
@@ -0,0 +1 @@
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":"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"}