@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 @@
1
+ {"version":3,"file":"index-vRLKumL8.mjs","sources":["../../src/renderers/Xlsx/index.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport ExcelJS from 'exceljs';\nimport Spreadsheet from 'x-data-spreadsheet';\nimport 'x-data-spreadsheet/dist/xspreadsheet.css';\nimport { convertWorkbookToSpreadsheetData } from '../../utils/excelDataConverter';\nimport { useTranslator } from '../../i18n/LocaleContext';\nimport { useFetcher } from '../../RequestContext';\nimport { RendererError } from '../RendererError';\nimport type { RendererHandle } from '../base.types';\n\ninterface XlsxRendererProps {\n url: string;\n}\n\nexport const XlsxRenderer = forwardRef<RendererHandle, XlsxRendererProps>(({ url }, ref) => {\n const t = useTranslator();\n const fetcher = useFetcher();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const spreadsheetRef = useRef<Spreadsheet | null>(null);\n const sheetDataRef = useRef<Record<string, unknown>[] | null>(null);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const resizeTimeoutRef = useRef<number | null>(null);\n const lastDimensionsRef = useRef({ width: 0, height: 0 });\n\n const calculateDimensions = useCallback(() => {\n if (!containerRef.current) return { width: 800, height: 600 };\n const rawWidth = containerRef.current.clientWidth;\n const rawHeight = containerRef.current.clientHeight;\n const width = rawWidth > 100 ? rawWidth : 800;\n const height = rawHeight > 100 ? rawHeight : 600;\n return { width, height };\n }, []);\n\n const mountSpreadsheet = useCallback(() => {\n if (!containerRef.current || !sheetDataRef.current) return;\n\n // 清空容器\n containerRef.current.innerHTML = '';\n spreadsheetRef.current = null;\n\n const { width, height } = calculateDimensions();\n const isMobile = width < 640;\n\n const s = new Spreadsheet(containerRef.current, {\n mode: 'read',\n showToolbar: false,\n showContextmenu: false,\n showGrid: true,\n row: {\n len: 100,\n height: 25,\n },\n col: {\n len: 26,\n width: isMobile ? 80 : 100,\n indexWidth: isMobile ? 40 : 60,\n minWidth: isMobile ? 40 : 60,\n },\n view: {\n height: () => height,\n width: () => width,\n },\n });\n\n s.loadData(sheetDataRef.current as unknown as Record<string, unknown>);\n spreadsheetRef.current = s;\n }, [calculateDimensions]);\n\n // 监听容器尺寸变化\n useEffect(() => {\n if (!containerRef.current) return;\n\n let isInitialRender = true;\n\n const updateDimensions = () => {\n if (isInitialRender) {\n isInitialRender = false;\n lastDimensionsRef.current = calculateDimensions();\n return;\n }\n\n const newDimensions = calculateDimensions();\n const lastDimensions = lastDimensionsRef.current;\n const widthDiff = Math.abs(lastDimensions.width - newDimensions.width);\n const heightDiff = Math.abs(lastDimensions.height - newDimensions.height);\n\n if (widthDiff < 10 && heightDiff < 10) return;\n\n lastDimensionsRef.current = newDimensions;\n\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n resizeTimeoutRef.current = window.setTimeout(() => {\n if (sheetDataRef.current) {\n mountSpreadsheet();\n }\n }, 500);\n };\n\n resizeObserverRef.current = new ResizeObserver(() => {\n updateDimensions();\n });\n\n resizeObserverRef.current.observe(containerRef.current);\n\n return () => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n }\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, [calculateDimensions, mountSpreadsheet]);\n\n useEffect(() => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (!url) return;\n\n let isMounted = true;\n\n const loadExcel = async () => {\n if (!containerRef.current) return;\n\n setLoading(true);\n setError(null);\n\n try {\n const response = await fetcher(url, {\n mode: 'cors',\n credentials: 'omit',\n redirect: 'follow',\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(t('xlsx.not_found'));\n } else if (response.status === 403) {\n throw new Error('无权限访问此文件');\n } else {\n throw new Error(`文件加载失败 (${response.status})`);\n }\n }\n\n const arrayBuffer = await response.arrayBuffer();\n\n if (arrayBuffer.byteLength === 0) {\n throw new Error('文件为空');\n }\n\n // 使用 exceljs 解析\n const workbook = new ExcelJS.Workbook();\n await workbook.xlsx.load(arrayBuffer);\n\n // 转换为 x-data-spreadsheet 数据格式\n const sheetData = convertWorkbookToSpreadsheetData(workbook);\n\n if (!isMounted) return;\n\n sheetDataRef.current = sheetData as unknown as Record<string, unknown>[];\n\n // 挂载 x-data-spreadsheet\n mountSpreadsheet();\n\n setLoading(false);\n } catch (err) {\n if (isMounted) {\n console.error('Excel 解析错误:', err);\n let errorMsg = t('xlsx.parse_failed');\n if (err instanceof Error) {\n errorMsg = err.message;\n }\n setError(errorMsg);\n setLoading(false);\n }\n }\n };\n\n const timer = setTimeout(() => {\n requestAnimationFrame(() => {\n loadExcel();\n });\n }, 100);\n\n return () => {\n isMounted = false;\n clearTimeout(timer);\n sheetDataRef.current = null;\n if (containerRef.current) {\n containerRef.current.innerHTML = '';\n }\n spreadsheetRef.current = null;\n };\n }, [url, mountSpreadsheet]);\n\n // 暴露接口给父组件\n useImperativeHandle(ref, () => ({\n getToolbarGroups: () => [],\n }), []);\n\n return (\n <div className=\"rfp-relative rfp-flex rfp-flex-col rfp-items-center rfp-w-full rfp-h-full\">\n {/* 加载状态 */}\n {loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <div className=\"rfp-text-center\">\n <div className=\"rfp-w-10 rfp-h-10 md:rfp-w-12 md:rfp-h-12 rfp-mx-auto rfp-mb-3 rfp-border-4 rfp-border-line-strong rfp-border-t-spinner-head rfp-rounded-full rfp-animate-spin\" />\n <p className=\"rfp-text-xs md:rfp-text-sm rfp-text-fg-secondary rfp-font-medium\">{t('xlsx.loading')}</p>\n </div>\n </div>\n )}\n\n {/* 错误状态 */}\n {error && !loading && (\n <div className=\"rfp-absolute rfp-inset-0 rfp-flex rfp-items-center rfp-justify-center rfp-bg-surface-toolbar rfp-backdrop-blur-sm rfp-z-10\">\n <RendererError message={t('xlsx.load_failed')} detail={error} />\n </div>\n )}\n\n {/* Spreadsheet 容器 */}\n {!error && (\n <div\n ref={containerRef}\n className=\"xlsx-spreadsheet-container rfp-w-full rfp-h-full\"\n style={{ opacity: loading ? 0 : 1 }}\n />\n )}\n </div>\n );\n});\n"],"names":["XlsxRenderer","forwardRef","url","ref","t","useTranslator","fetcher","useFetcher","loading","setLoading","useState","error","setError","containerRef","useRef","spreadsheetRef","sheetDataRef","resizeObserverRef","resizeTimeoutRef","lastDimensionsRef","calculateDimensions","useCallback","rawWidth","rawHeight","width","height","mountSpreadsheet","isMobile","s","Spreadsheet","useEffect","isInitialRender","updateDimensions","newDimensions","lastDimensions","widthDiff","heightDiff","isMounted","loadExcel","response","arrayBuffer","workbook","ExcelJS","sheetData","convertWorkbookToSpreadsheetData","err","errorMsg","timer","useImperativeHandle","jsxs","jsx","RendererError"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { useState as m, useEffect as d } from "react";
2
+ import { codeToHtml as h } from "shiki";
3
+ import { b as p } from "./index-DreA69iU.mjs";
4
+ function y(e, s) {
5
+ const o = p(), [r, n] = m(""), [i, c] = m([]), [u, l] = m(!0);
6
+ return d(() => {
7
+ let a = !1;
8
+ return l(!0), h(e, {
9
+ lang: s,
10
+ theme: o === "light" ? "github-light" : "dark-plus",
11
+ transformers: [{
12
+ name: "line-numbers",
13
+ line(t, f) {
14
+ t.properties["data-line"] = f, this.addClassToHast(t, "line");
15
+ }
16
+ }]
17
+ }).then((t) => {
18
+ a || (n(t), c(g(t)), l(!1));
19
+ }).catch(() => {
20
+ a || (n(""), c([]), l(!1));
21
+ }), () => {
22
+ a = !0;
23
+ };
24
+ }, [e, s, o]), { html: r, lineHtmls: i, loading: u };
25
+ }
26
+ function g(e) {
27
+ if (typeof window > "u" || !e) return [];
28
+ const r = new DOMParser().parseFromString(e, "text/html").querySelector("code");
29
+ if (!r) return [];
30
+ const n = r.querySelectorAll(".line");
31
+ return Array.from(n).map((i) => i.innerHTML);
32
+ }
33
+ export {
34
+ y as u
35
+ };
36
+ //# sourceMappingURL=useShikiHighlight-C6nJcETW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useShikiHighlight-C6nJcETW.mjs","sources":["../../src/hooks/useShikiHighlight.ts"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { codeToHtml, type ShikiTransformer } from 'shiki';\nimport { useResolvedTheme } from '../ThemeContext';\n\n/**\n * 用 shiki 把代码高亮成 HTML(与 vue-file-preview 同引擎、同主题,保证两端视觉一致)。\n *\n * - dark 主题用 `dark-plus`(VSCode Dark Plus)\n * - light 主题用 `github-light`(GitHub Light)\n *\n * shiki 输出的 <pre> 自带 inline 背景/前景色,主题切换时必须重新高亮,\n * 因此 resolvedTheme 进入依赖数组。\n *\n * @returns\n * - `html`: 完整的 shiki 输出 HTML(含 pre/code 包裹),markdown 等场景使用\n * - `lineHtmls`: 拆分后的每一行 HTML(用于双列行号布局)\n * - `loading`: 是否正在高亮\n */\nexport function useShikiHighlight(\n code: string,\n lang: string,\n): { html: string; lineHtmls: string[]; loading: boolean } {\n const resolvedTheme = useResolvedTheme();\n const [html, setHtml] = useState('');\n const [lineHtmls, setLineHtmls] = useState<string[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n\n const lineNumbersTransformer: ShikiTransformer = {\n name: 'line-numbers',\n line(node, line) {\n node.properties['data-line'] = line;\n this.addClassToHast(node, 'line');\n },\n };\n\n codeToHtml(code, {\n lang,\n theme: resolvedTheme === 'light' ? 'github-light' : 'dark-plus',\n transformers: [lineNumbersTransformer],\n })\n .then((out) => {\n if (!cancelled) {\n setHtml(out);\n setLineHtmls(extractLines(out));\n setLoading(false);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setHtml('');\n setLineHtmls([]);\n setLoading(false);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [code, lang, resolvedTheme]);\n\n return { html, lineHtmls, loading };\n}\n\n/**\n * 从 shiki 输出的 HTML 中提取每一行的内容(保留高亮标签)\n */\nfunction extractLines(html: string): string[] {\n if (typeof window === 'undefined' || !html) return [];\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n const codeElement = doc.querySelector('code');\n if (!codeElement) return [];\n const lineElements = codeElement.querySelectorAll('.line');\n return Array.from(lineElements).map((line) => line.innerHTML);\n}\n"],"names":["useShikiHighlight","code","lang","resolvedTheme","useResolvedTheme","html","setHtml","useState","lineHtmls","setLineHtmls","loading","setLoading","useEffect","cancelled","codeToHtml","node","line","out","extractLines","codeElement","lineElements"],"mappings":";;;AAkBO,SAASA,EACdC,GACAC,GACyD;AACzD,QAAMC,IAAgBC,EAAA,GAChB,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAE,GAC7B,CAACC,GAAWC,CAAY,IAAIF,EAAmB,CAAA,CAAE,GACjD,CAACG,GAASC,CAAU,IAAIJ,EAAS,EAAI;AAE3C,SAAAK,EAAU,MAAM;AACd,QAAIC,IAAY;AAChB,WAAAF,EAAW,EAAI,GAUfG,EAAWb,GAAM;AAAA,MACf,MAAAC;AAAA,MACA,OAAOC,MAAkB,UAAU,iBAAiB;AAAA,MACpD,cAAc,CAXiC;AAAA,QAC/C,MAAM;AAAA,QACN,KAAKY,GAAMC,GAAM;AACf,UAAAD,EAAK,WAAW,WAAW,IAAIC,GAC/B,KAAK,eAAeD,GAAM,MAAM;AAAA,QAClC;AAAA,MAAA,CAMqC;AAAA,IAAA,CACtC,EACE,KAAK,CAACE,MAAQ;AACb,MAAKJ,MACHP,EAAQW,CAAG,GACXR,EAAaS,EAAaD,CAAG,CAAC,GAC9BN,EAAW,EAAK;AAAA,IAEpB,CAAC,EACA,MAAM,MAAM;AACX,MAAKE,MACHP,EAAQ,EAAE,GACVG,EAAa,CAAA,CAAE,GACfE,EAAW,EAAK;AAAA,IAEpB,CAAC,GACI,MAAM;AACX,MAAAE,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACZ,GAAMC,GAAMC,CAAa,CAAC,GAEvB,EAAE,MAAAE,GAAM,WAAAG,GAAW,SAAAE,EAAA;AAC5B;AAKA,SAASQ,EAAab,GAAwB;AAC5C,MAAI,OAAO,SAAW,OAAe,CAACA,UAAa,CAAA;AAGnD,QAAMc,IAFS,IAAI,UAAA,EACA,gBAAgBd,GAAM,WAAW,EAC5B,cAAc,MAAM;AAC5C,MAAI,CAACc,EAAa,QAAO,CAAA;AACzB,QAAMC,IAAeD,EAAY,iBAAiB,OAAO;AACzD,SAAO,MAAM,KAAKC,CAAY,EAAE,IAAI,CAACJ,MAASA,EAAK,SAAS;AAC9D;"}
@@ -9,6 +9,7 @@ export interface FilePreviewToolbarProps {
9
9
  t: Translator;
10
10
  onDownload: () => void;
11
11
  onClose?: () => void;
12
+ showDownload: boolean;
12
13
  }
13
14
  /**
14
15
  * 文件预览顶部工具栏组件
@@ -1 +1 @@
1
- {"version":3,"file":"FilePreviewToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/preview/FilePreviewToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,CAAC,EAAE,UAAU,CAAC;IACd,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAuFhE,CAAC"}
1
+ {"version":3,"file":"FilePreviewToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/preview/FilePreviewToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,CAAC,EAAE,UAAU,CAAC;IACd,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4FhE,CAAC"}
@@ -4,11 +4,13 @@ export interface ToolbarButtonProps {
4
4
  label: string;
5
5
  onClick: () => void;
6
6
  disabled?: boolean;
7
+ /** 激活状态:true 时按钮显示高亮样式 */
8
+ active?: boolean;
7
9
  ariaKeyshortcuts?: string;
8
10
  }
9
11
  /**
10
12
  * 工具栏按钮组件
11
- * 支持 tooltip、disabled 状态和 aria 属性
13
+ * 支持 tooltip、disabled 状态、active 高亮和 aria 属性
12
14
  */
13
15
  export declare const ToolbarButton: React.FC<ToolbarButtonProps>;
14
16
  //# sourceMappingURL=ToolbarButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../../../src/components/preview/ToolbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA2BtD,CAAC"}
1
+ {"version":3,"file":"ToolbarButton.d.ts","sourceRoot":"","sources":["../../../src/components/preview/ToolbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkCtD,CAAC"}
@@ -1,9 +1,3 @@
1
- export * from './types';
2
- export * from './rendererReducer';
3
- export * from './useFilePreviewState';
4
1
  export * from './useKeyboardNavigation';
5
- export * from './useBookRenderer';
6
2
  export * from './useThemeMode';
7
- export * from './useImageAutoFit';
8
- export * from './useToolbarConfig';
9
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC"}
@@ -8,11 +8,13 @@
8
8
  * 因此 resolvedTheme 进入依赖数组。
9
9
  *
10
10
  * @returns
11
- * - `html`: 高亮后的 HTML 字符串(失败或加载中为 '')
11
+ * - `html`: 完整的 shiki 输出 HTML(含 pre/code 包裹),markdown 等场景使用
12
+ * - `lineHtmls`: 拆分后的每一行 HTML(用于双列行号布局)
12
13
  * - `loading`: 是否正在高亮
13
14
  */
14
15
  export declare function useShikiHighlight(code: string, lang: string): {
15
16
  html: string;
17
+ lineHtmls: string[];
16
18
  loading: boolean;
17
19
  };
18
20
  //# sourceMappingURL=useShikiHighlight.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useShikiHighlight.d.ts","sourceRoot":"","sources":["../../src/hooks/useShikiHighlight.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA8BhG"}
1
+ {"version":3,"file":"useShikiHighlight.d.ts","sourceRoot":"","sources":["../../src/hooks/useShikiHighlight.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2CzD"}