@hkyhy/marsun-components-core 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/File/FilePreview/FilePreviewContent.js +54 -47
- package/dist/components/File/FilePreview/FilePreviewContent.js.map +1 -1
- package/dist/components/File/FilePreview/style.module.scss.js +17 -16
- package/dist/components/File/FilePreview/style.module.scss.js.map +1 -1
- package/dist/components/File/FilePreviewLink/index.d.ts +2 -0
- package/dist/components/File/FilePreviewLink/index.js +46 -33
- package/dist/components/File/FilePreviewLink/index.js.map +1 -1
- package/dist/components/File/FilePreviewLink/style.module.scss.js +7 -5
- package/dist/components/File/FilePreviewLink/style.module.scss.js.map +1 -1
- package/dist/components/LlmFormattedText/LlmFormattedText/index.d.ts +8 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/index.js +42 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/index.js.map +1 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/style.module.scss.js +17 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/style.module.scss.js.map +1 -0
- package/dist/components/LlmFormattedText/index.d.ts +4 -0
- package/dist/components/LlmFormattedText/parseLlmText.d.ts +14 -0
- package/dist/components/LlmFormattedText/parseLlmText.js +77 -0
- package/dist/components/LlmFormattedText/parseLlmText.js.map +1 -0
- package/dist/components/Sparkline/Sparkline/index.d.ts +11 -0
- package/dist/components/Sparkline/Sparkline/index.js +46 -0
- package/dist/components/Sparkline/Sparkline/index.js.map +1 -0
- package/dist/components/Sparkline/Sparkline/style.module.scss.js +8 -0
- package/dist/components/Sparkline/Sparkline/style.module.scss.js.map +1 -0
- package/dist/components/Sparkline/index.d.ts +2 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -73
- package/dist/index.js.map +1 -1
- package/dist/marsun-components-core.css +1 -1
- package/dist/styles/global.css +1 -1
- package/package.json +1 -1
|
@@ -1,83 +1,90 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { Empty as u, Spin as
|
|
3
|
-
import { useRef as
|
|
1
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { Empty as u, Spin as x } from "antd";
|
|
3
|
+
import { useRef as h, useState as g, useEffect as N } from "react";
|
|
4
4
|
import { getPreviewKind as E, needsBlobPreview as P } from "../previewKind.js";
|
|
5
|
-
import
|
|
5
|
+
import o from "./style.module.scss.js";
|
|
6
6
|
import b from "classnames";
|
|
7
|
-
async function
|
|
8
|
-
const e = await fetch(
|
|
7
|
+
async function H(r) {
|
|
8
|
+
const e = await fetch(r);
|
|
9
9
|
if (!e.ok) throw new Error(`预览加载失败 (${e.status})`);
|
|
10
10
|
return e.arrayBuffer();
|
|
11
11
|
}
|
|
12
|
-
async function
|
|
13
|
-
|
|
12
|
+
async function B(r, e) {
|
|
13
|
+
var d;
|
|
14
|
+
const [{ default: s }] = await Promise.all([
|
|
14
15
|
import("@js-preview/excel"),
|
|
15
16
|
Promise.resolve({ })
|
|
16
|
-
]),
|
|
17
|
-
|
|
17
|
+
]), a = Math.max(
|
|
18
|
+
((d = r.parentElement) == null ? void 0 : d.clientHeight) ?? 0,
|
|
19
|
+
Math.round(window.innerHeight * 0.65),
|
|
20
|
+
480
|
|
21
|
+
);
|
|
22
|
+
r.style.height = `${a}px`;
|
|
23
|
+
const t = s.init(r);
|
|
24
|
+
return await t.preview(e), () => t.destroy();
|
|
18
25
|
}
|
|
19
|
-
async function
|
|
20
|
-
const { renderAsync:
|
|
21
|
-
await
|
|
26
|
+
async function C(r, e) {
|
|
27
|
+
const { renderAsync: s } = await import("docx-preview"), a = new Blob([e]);
|
|
28
|
+
await s(a, r, r, {
|
|
22
29
|
inWrapper: !0,
|
|
23
30
|
ignoreWidth: !1,
|
|
24
31
|
ignoreHeight: !1,
|
|
25
32
|
breakPages: !0
|
|
26
33
|
});
|
|
27
34
|
}
|
|
28
|
-
async function
|
|
29
|
-
const { init:
|
|
30
|
-
return await
|
|
35
|
+
async function M(r, e, s) {
|
|
36
|
+
const { init: a } = await import("pptx-preview"), t = a(r, { width: s, height: Math.round(s * 0.5625), mode: "list" });
|
|
37
|
+
return await t.preview(e), () => t.destroy();
|
|
31
38
|
}
|
|
32
|
-
function
|
|
33
|
-
const
|
|
34
|
-
|
|
39
|
+
function T(r, e) {
|
|
40
|
+
const s = new TextDecoder("utf-8"), a = document.createElement("pre");
|
|
41
|
+
a.className = o["file-preview-text"], a.textContent = s.decode(e), r.appendChild(a);
|
|
35
42
|
}
|
|
36
|
-
const
|
|
37
|
-
file:
|
|
43
|
+
const D = ({
|
|
44
|
+
file: r,
|
|
38
45
|
previewUrl: e,
|
|
39
|
-
unsupportedMessage:
|
|
46
|
+
unsupportedMessage: s = "暂不支持预览此文件类型"
|
|
40
47
|
}) => {
|
|
41
|
-
const
|
|
42
|
-
return
|
|
43
|
-
var
|
|
44
|
-
const f =
|
|
48
|
+
const a = h(null), t = h(void 0), [d, m] = g(!1), [p, w] = g(null), i = E(r);
|
|
49
|
+
return N(() => {
|
|
50
|
+
var v;
|
|
51
|
+
const f = a.current;
|
|
45
52
|
if (!f || !e) return;
|
|
46
|
-
let
|
|
47
|
-
return (
|
|
48
|
-
if (
|
|
49
|
-
|
|
53
|
+
let l = !1;
|
|
54
|
+
return (v = t.current) == null || v.call(t), t.current = void 0, f.innerHTML = "", w(null), (async () => {
|
|
55
|
+
if (i !== "image" && !(i === "pdf" || i === "iframe") && !(i === "video" || i === "audio") && i !== "unsupported") {
|
|
56
|
+
m(!0);
|
|
50
57
|
try {
|
|
51
|
-
const c = await
|
|
52
|
-
if (
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
else if (
|
|
56
|
-
await
|
|
57
|
-
else if (
|
|
58
|
+
const c = await H(e);
|
|
59
|
+
if (l) return;
|
|
60
|
+
if (i === "excel")
|
|
61
|
+
t.current = await B(f, c);
|
|
62
|
+
else if (i === "word")
|
|
63
|
+
await C(f, c);
|
|
64
|
+
else if (i === "ppt") {
|
|
58
65
|
const y = f.clientWidth || 852;
|
|
59
|
-
|
|
60
|
-
} else
|
|
66
|
+
t.current = await M(f, c, y);
|
|
67
|
+
} else i === "text" && T(f, c);
|
|
61
68
|
} catch (c) {
|
|
62
|
-
|
|
69
|
+
l || w(c instanceof Error ? c.message : "预览加载失败");
|
|
63
70
|
} finally {
|
|
64
|
-
|
|
71
|
+
l || m(!1);
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
})(), () => {
|
|
68
75
|
var c;
|
|
69
|
-
|
|
76
|
+
l = !0, (c = t.current) == null || c.call(t), t.current = void 0, f.innerHTML = "";
|
|
70
77
|
};
|
|
71
|
-
}, [e,
|
|
78
|
+
}, [e, i, r.id, r.name]), e ? i === "image" ? /* @__PURE__ */ n("div", { className: o["file-preview-media-wrap"], children: /* @__PURE__ */ n("img", { src: e, alt: r.name, className: o["file-preview-image"] }) }) : i === "pdf" || i === "iframe" ? /* @__PURE__ */ n(
|
|
72
79
|
"iframe",
|
|
73
80
|
{
|
|
74
81
|
src: e,
|
|
75
|
-
title:
|
|
76
|
-
className:
|
|
82
|
+
title: r.name,
|
|
83
|
+
className: o["file-preview-iframe"]
|
|
77
84
|
}
|
|
78
|
-
) :
|
|
85
|
+
) : i === "video" ? /* @__PURE__ */ n("div", { className: o["file-preview-media-wrap"], children: /* @__PURE__ */ n("video", { src: e, controls: !0, className: o["file-preview-video"] }) }) : i === "audio" ? /* @__PURE__ */ n("div", { className: o["file-preview-audio-wrap"], children: /* @__PURE__ */ n("audio", { src: e, controls: !0, className: o["file-preview-audio"] }) }) : i === "unsupported" ? /* @__PURE__ */ n(u, { description: s }) : P(i) ? /* @__PURE__ */ n("div", { className: b(o["file-preview-office"], o["file-preview-office-wrap"]), children: /* @__PURE__ */ n(x, { spinning: d, wrapperClassName: o["file-preview-office-spin"], children: p ? /* @__PURE__ */ n(u, { description: p }) : /* @__PURE__ */ n("div", { ref: a, className: o["file-preview-office-inner"] }) }) }) : /* @__PURE__ */ n(u, { description: s }) : /* @__PURE__ */ n(u, { description: "无可预览地址" });
|
|
79
86
|
};
|
|
80
87
|
export {
|
|
81
|
-
|
|
88
|
+
D as default
|
|
82
89
|
};
|
|
83
90
|
//# sourceMappingURL=FilePreviewContent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewContent.js","sources":["../../../../src/components/File/FilePreview/FilePreviewContent.tsx"],"sourcesContent":["import { Empty, Spin } from 'antd';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getPreviewKind, needsBlobPreview } from '../previewKind';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\ninterface FilePreviewContentProps {\n file: FileDisplayItem;\n previewUrl?: string;\n unsupportedMessage?: string;\n}\n\nasync function fetchPreviewBlob(url: string): Promise<ArrayBuffer> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`预览加载失败 (${res.status})`);\n return res.arrayBuffer();\n}\n\nasync function renderExcel(container: HTMLElement, data: ArrayBuffer) {\n const [{ default: jsPreviewExcel }] = await Promise.all([\n import('@js-preview/excel'),\n import('@js-preview/excel/lib/index.css'),\n ]);\n const instance = jsPreviewExcel.init(container);\n await instance.preview(data);\n return () => instance.destroy();\n}\n\nasync function renderWord(container: HTMLElement, data: ArrayBuffer) {\n const { renderAsync } = await import('docx-preview');\n const blob = new Blob([data]);\n await renderAsync(blob, container, container, {\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n breakPages: true,\n });\n}\n\nasync function renderPpt(container: HTMLElement, data: ArrayBuffer, width: number) {\n const { init } = await import('pptx-preview');\n const previewer = init(container, { width, height: Math.round(width * 0.5625), mode: 'list' });\n await previewer.preview(data);\n return () => previewer.destroy();\n}\n\nfunction renderText(container: HTMLElement, data: ArrayBuffer) {\n const decoder = new TextDecoder('utf-8');\n const pre = document.createElement('pre');\n pre.className = styles['file-preview-text'] ?? '';\n pre.textContent = decoder.decode(data);\n container.appendChild(pre);\n}\n\nconst FilePreviewContent: React.FC<FilePreviewContentProps> = ({\n file,\n previewUrl,\n unsupportedMessage = '暂不支持预览此文件类型',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const cleanupRef = useRef<(() => void) | void>(undefined);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const kind = getPreviewKind(file);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !previewUrl) return undefined;\n\n let cancelled = false;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n setError(null);\n\n const run = async () => {\n if (kind === 'image') return;\n if (kind === 'pdf' || kind === 'iframe') return;\n if (kind === 'video' || kind === 'audio') return;\n if (kind === 'unsupported') return;\n\n setLoading(true);\n try {\n const data = await fetchPreviewBlob(previewUrl);\n if (cancelled) return;\n\n if (kind === 'excel') {\n cleanupRef.current = await renderExcel(container, data);\n } else if (kind === 'word') {\n await renderWord(container, data);\n } else if (kind === 'ppt') {\n const width = container.clientWidth || 852;\n cleanupRef.current = await renderPpt(container, data, width);\n } else if (kind === 'text') {\n renderText(container, data);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : '预览加载失败');\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n };\n }, [previewUrl, kind, file.id, file.name]);\n\n if (!previewUrl) {\n return <Empty description=\"无可预览地址\" />;\n }\n\n if (kind === 'image') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <img src={previewUrl} alt={file.name} className={styles['file-preview-image']} />\n </div>\n );\n }\n\n if (kind === 'pdf' || kind === 'iframe') {\n return (\n <iframe\n src={previewUrl}\n title={file.name}\n className={styles['file-preview-iframe']}\n />\n );\n }\n\n if (kind === 'video') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <video src={previewUrl} controls className={styles['file-preview-video']} />\n </div>\n );\n }\n\n if (kind === 'audio') {\n return (\n <div className={styles['file-preview-audio-wrap']}>\n <audio src={previewUrl} controls className={styles['file-preview-audio']} />\n </div>\n );\n }\n\n if (kind === 'unsupported') {\n return <Empty description={unsupportedMessage} />;\n }\n\n if (needsBlobPreview(kind)) {\n return (\n <div className={classNames(styles['file-preview-office'], styles['file-preview-office-wrap'])}>\n <Spin spinning={loading}>\n {error ? <Empty description={error} /> : <div ref={containerRef} className={styles['file-preview-office-inner']} />}\n </Spin>\n </div>\n );\n }\n\n return <Empty description={unsupportedMessage} />;\n};\n\nexport default FilePreviewContent;\n"],"names":["fetchPreviewBlob","url","res","renderExcel","container","data","jsPreviewExcel","instance","renderWord","renderAsync","blob","renderPpt","width","init","previewer","renderText","decoder","pre","styles","FilePreviewContent","file","previewUrl","unsupportedMessage","containerRef","useRef","cleanupRef","loading","setLoading","useState","error","setError","kind","getPreviewKind","useEffect","cancelled","
|
|
1
|
+
{"version":3,"file":"FilePreviewContent.js","sources":["../../../../src/components/File/FilePreview/FilePreviewContent.tsx"],"sourcesContent":["import { Empty, Spin } from 'antd';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getPreviewKind, needsBlobPreview } from '../previewKind';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\ninterface FilePreviewContentProps {\n file: FileDisplayItem;\n previewUrl?: string;\n unsupportedMessage?: string;\n}\n\nasync function fetchPreviewBlob(url: string): Promise<ArrayBuffer> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`预览加载失败 (${res.status})`);\n return res.arrayBuffer();\n}\n\nasync function renderExcel(container: HTMLElement, data: ArrayBuffer) {\n const [{ default: jsPreviewExcel }] = await Promise.all([\n import('@js-preview/excel'),\n import('@js-preview/excel/lib/index.css'),\n ]);\n const height = Math.max(\n container.parentElement?.clientHeight ?? 0,\n Math.round(window.innerHeight * 0.65),\n 480,\n );\n container.style.height = `${height}px`;\n const instance = jsPreviewExcel.init(container);\n await instance.preview(data);\n return () => instance.destroy();\n}\n\nasync function renderWord(container: HTMLElement, data: ArrayBuffer) {\n const { renderAsync } = await import('docx-preview');\n const blob = new Blob([data]);\n await renderAsync(blob, container, container, {\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n breakPages: true,\n });\n}\n\nasync function renderPpt(container: HTMLElement, data: ArrayBuffer, width: number) {\n const { init } = await import('pptx-preview');\n const previewer = init(container, { width, height: Math.round(width * 0.5625), mode: 'list' });\n await previewer.preview(data);\n return () => previewer.destroy();\n}\n\nfunction renderText(container: HTMLElement, data: ArrayBuffer) {\n const decoder = new TextDecoder('utf-8');\n const pre = document.createElement('pre');\n pre.className = styles['file-preview-text'] ?? '';\n pre.textContent = decoder.decode(data);\n container.appendChild(pre);\n}\n\nconst FilePreviewContent: React.FC<FilePreviewContentProps> = ({\n file,\n previewUrl,\n unsupportedMessage = '暂不支持预览此文件类型',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const cleanupRef = useRef<(() => void) | void>(undefined);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const kind = getPreviewKind(file);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !previewUrl) return undefined;\n\n let cancelled = false;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n setError(null);\n\n const run = async () => {\n if (kind === 'image') return;\n if (kind === 'pdf' || kind === 'iframe') return;\n if (kind === 'video' || kind === 'audio') return;\n if (kind === 'unsupported') return;\n\n setLoading(true);\n try {\n const data = await fetchPreviewBlob(previewUrl);\n if (cancelled) return;\n\n if (kind === 'excel') {\n cleanupRef.current = await renderExcel(container, data);\n } else if (kind === 'word') {\n await renderWord(container, data);\n } else if (kind === 'ppt') {\n const width = container.clientWidth || 852;\n cleanupRef.current = await renderPpt(container, data, width);\n } else if (kind === 'text') {\n renderText(container, data);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : '预览加载失败');\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n cleanupRef.current?.();\n cleanupRef.current = undefined;\n container.innerHTML = '';\n };\n }, [previewUrl, kind, file.id, file.name]);\n\n if (!previewUrl) {\n return <Empty description=\"无可预览地址\" />;\n }\n\n if (kind === 'image') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <img src={previewUrl} alt={file.name} className={styles['file-preview-image']} />\n </div>\n );\n }\n\n if (kind === 'pdf' || kind === 'iframe') {\n return (\n <iframe\n src={previewUrl}\n title={file.name}\n className={styles['file-preview-iframe']}\n />\n );\n }\n\n if (kind === 'video') {\n return (\n <div className={styles['file-preview-media-wrap']}>\n <video src={previewUrl} controls className={styles['file-preview-video']} />\n </div>\n );\n }\n\n if (kind === 'audio') {\n return (\n <div className={styles['file-preview-audio-wrap']}>\n <audio src={previewUrl} controls className={styles['file-preview-audio']} />\n </div>\n );\n }\n\n if (kind === 'unsupported') {\n return <Empty description={unsupportedMessage} />;\n }\n\n if (needsBlobPreview(kind)) {\n return (\n <div className={classNames(styles['file-preview-office'], styles['file-preview-office-wrap'])}>\n <Spin spinning={loading} wrapperClassName={styles['file-preview-office-spin']}>\n {error ? <Empty description={error} /> : <div ref={containerRef} className={styles['file-preview-office-inner']} />}\n </Spin>\n </div>\n );\n }\n\n return <Empty description={unsupportedMessage} />;\n};\n\nexport default FilePreviewContent;\n"],"names":["fetchPreviewBlob","url","res","renderExcel","container","data","jsPreviewExcel","height","_a","instance","renderWord","renderAsync","blob","renderPpt","width","init","previewer","renderText","decoder","pre","styles","FilePreviewContent","file","previewUrl","unsupportedMessage","containerRef","useRef","cleanupRef","loading","setLoading","useState","error","setError","kind","getPreviewKind","useEffect","cancelled","err","jsx","Empty","needsBlobPreview","classNames","Spin"],"mappings":";;;;;;AAaA,eAAeA,EAAiBC,GAAmC;AACjE,QAAMC,IAAM,MAAM,MAAMD,CAAG;AAC3B,MAAI,CAACC,EAAI,GAAI,OAAM,IAAI,MAAM,WAAWA,EAAI,MAAM,GAAG;AACrD,SAAOA,EAAI,YAAA;AACb;AAEA,eAAeC,EAAYC,GAAwBC,GAAmB;;AACpE,QAAM,CAAC,EAAE,SAASC,EAAA,CAAgB,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtD,OAAO,mBAAmB;AAAA,IAC1B,OAAO,0DAAiC;AAAA,EAAA,CACzC,GACKC,IAAS,KAAK;AAAA,MAClBC,IAAAJ,EAAU,kBAAV,gBAAAI,EAAyB,iBAAgB;AAAA,IACzC,KAAK,MAAM,OAAO,cAAc,IAAI;AAAA,IACpC;AAAA,EAAA;AAEF,EAAAJ,EAAU,MAAM,SAAS,GAAGG,CAAM;AAClC,QAAME,IAAWH,EAAe,KAAKF,CAAS;AAC9C,eAAMK,EAAS,QAAQJ,CAAI,GACpB,MAAMI,EAAS,QAAA;AACxB;AAEA,eAAeC,EAAWN,GAAwBC,GAAmB;AACnE,QAAM,EAAE,aAAAM,EAAA,IAAgB,MAAM,OAAO,cAAc,GAC7CC,IAAO,IAAI,KAAK,CAACP,CAAI,CAAC;AAC5B,QAAMM,EAAYC,GAAMR,GAAWA,GAAW;AAAA,IAC5C,WAAW;AAAA,IACX,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,EAAA,CACb;AACH;AAEA,eAAeS,EAAUT,GAAwBC,GAAmBS,GAAe;AACjF,QAAM,EAAE,MAAAC,EAAA,IAAS,MAAM,OAAO,cAAc,GACtCC,IAAYD,EAAKX,GAAW,EAAE,OAAAU,GAAO,QAAQ,KAAK,MAAMA,IAAQ,MAAM,GAAG,MAAM,QAAQ;AAC7F,eAAME,EAAU,QAAQX,CAAI,GACrB,MAAMW,EAAU,QAAA;AACzB;AAEA,SAASC,EAAWb,GAAwBC,GAAmB;AAC7D,QAAMa,IAAU,IAAI,YAAY,OAAO,GACjCC,IAAM,SAAS,cAAc,KAAK;AACxC,EAAAA,EAAI,YAAYC,EAAO,mBAAmB,GAC1CD,EAAI,cAAcD,EAAQ,OAAOb,CAAI,GACrCD,EAAU,YAAYe,CAAG;AAC3B;AAEA,MAAME,IAAwD,CAAC;AAAA,EAC7D,MAAAC;AAAA,EACA,YAAAC;AAAA,EACA,oBAAAC,IAAqB;AACvB,MAAM;AACJ,QAAMC,IAAeC,EAAuB,IAAI,GAC1CC,IAAaD,EAA4B,MAAS,GAClD,CAACE,GAASC,CAAU,IAAIC,EAAS,EAAK,GACtC,CAACC,GAAOC,CAAQ,IAAIF,EAAwB,IAAI,GAChDG,IAAOC,EAAeZ,CAAI;AAoDhC,SAlDAa,EAAU,MAAM;;AACd,UAAM/B,IAAYqB,EAAa;AAC/B,QAAI,CAACrB,KAAa,CAACmB,EAAY;AAE/B,QAAIa,IAAY;AAChB,YAAA5B,IAAAmB,EAAW,YAAX,QAAAnB,EAAA,KAAAmB,IACAA,EAAW,UAAU,QACrBvB,EAAU,YAAY,IACtB4B,EAAS,IAAI,IAED,YAAY;AACtB,UAAIC,MAAS,WACT,EAAAA,MAAS,SAASA,MAAS,aAC3B,EAAAA,MAAS,WAAWA,MAAS,YAC7BA,MAAS,eAEb;AAAA,QAAAJ,EAAW,EAAI;AACf,YAAI;AACF,gBAAMxB,IAAO,MAAML,EAAiBuB,CAAU;AAC9C,cAAIa,EAAW;AAEf,cAAIH,MAAS;AACX,YAAAN,EAAW,UAAU,MAAMxB,EAAYC,GAAWC,CAAI;AAAA,mBAC7C4B,MAAS;AAClB,kBAAMvB,EAAWN,GAAWC,CAAI;AAAA,mBACvB4B,MAAS,OAAO;AACzB,kBAAMnB,IAAQV,EAAU,eAAe;AACvC,YAAAuB,EAAW,UAAU,MAAMd,EAAUT,GAAWC,GAAMS,CAAK;AAAA,UAC7D,MAAA,CAAWmB,MAAS,UAClBhB,EAAWb,GAAWC,CAAI;AAAA,QAE9B,SAASgC,GAAK;AACZ,UAAKD,KACHJ,EAASK,aAAe,QAAQA,EAAI,UAAU,QAAQ;AAAA,QAE1D,UAAA;AACE,UAAKD,KAAWP,EAAW,EAAK;AAAA,QAClC;AAAA;AAAA,IACF,GAEK,GAEE,MAAM;;AACX,MAAAO,IAAY,KACZ5B,IAAAmB,EAAW,YAAX,QAAAnB,EAAA,KAAAmB,IACAA,EAAW,UAAU,QACrBvB,EAAU,YAAY;AAAA,IACxB;AAAA,EACF,GAAG,CAACmB,GAAYU,GAAMX,EAAK,IAAIA,EAAK,IAAI,CAAC,GAEpCC,IAIDU,MAAS,4BAER,OAAA,EAAI,WAAWb,EAAO,yBAAyB,GAC9C,UAAA,gBAAAkB,EAAC,OAAA,EAAI,KAAKf,GAAY,KAAKD,EAAK,MAAM,WAAWF,EAAO,oBAAoB,GAAG,GACjF,IAIAa,MAAS,SAASA,MAAS,WAE3B,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKf;AAAA,MACL,OAAOD,EAAK;AAAA,MACZ,WAAWF,EAAO,qBAAqB;AAAA,IAAA;AAAA,EAAA,IAKzCa,MAAS,4BAER,OAAA,EAAI,WAAWb,EAAO,yBAAyB,GAC9C,UAAA,gBAAAkB,EAAC,SAAA,EAAM,KAAKf,GAAY,UAAQ,IAAC,WAAWH,EAAO,oBAAoB,GAAG,GAC5E,IAIAa,MAAS,4BAER,OAAA,EAAI,WAAWb,EAAO,yBAAyB,GAC9C,UAAA,gBAAAkB,EAAC,SAAA,EAAM,KAAKf,GAAY,UAAQ,IAAC,WAAWH,EAAO,oBAAoB,GAAG,GAC5E,IAIAa,MAAS,gBACJ,gBAAAK,EAACC,GAAA,EAAM,aAAaf,EAAA,CAAoB,IAG7CgB,EAAiBP,CAAI,IAErB,gBAAAK,EAAC,OAAA,EAAI,WAAWG,EAAWrB,EAAO,qBAAqB,GAAGA,EAAO,0BAA0B,CAAC,GAC1F,UAAA,gBAAAkB,EAACI,GAAA,EAAK,UAAUd,GAAS,kBAAkBR,EAAO,0BAA0B,GACzE,UAAAW,IAAQ,gBAAAO,EAACC,GAAA,EAAM,aAAaR,GAAO,IAAK,gBAAAO,EAAC,OAAA,EAAI,KAAKb,GAAc,WAAWL,EAAO,2BAA2B,EAAA,CAAG,GACnH,GACF,IAIG,gBAAAkB,EAACC,GAAA,EAAM,aAAaf,EAAA,CAAoB,IAnDtC,gBAAAc,EAACC,GAAA,EAAM,aAAY,SAAA,CAAS;AAoDvC;"}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
const e = {
|
|
2
|
-
"file-preview": "_file-
|
|
3
|
-
"file-preview-header": "_file-preview-
|
|
4
|
-
"file-preview-info": "_file-preview-
|
|
5
|
-
"file-preview-icon": "_file-preview-
|
|
6
|
-
"file-preview-name": "_file-preview-
|
|
7
|
-
"file-preview-size": "_file-preview-
|
|
8
|
-
"file-preview-body": "_file-preview-
|
|
9
|
-
"file-preview-iframe": "_file-preview-
|
|
10
|
-
"file-preview-media-wrap": "_file-preview-media-
|
|
11
|
-
"file-preview-image": "_file-preview-
|
|
12
|
-
"file-preview-video": "_file-preview-
|
|
13
|
-
"file-preview-audio-wrap": "_file-preview-audio-
|
|
14
|
-
"file-preview-audio": "_file-preview-
|
|
15
|
-
"file-preview-office-wrap": "_file-preview-office-
|
|
16
|
-
"file-preview-office-
|
|
17
|
-
"file-preview-
|
|
2
|
+
"file-preview": "_file-preview_m0qyk_1",
|
|
3
|
+
"file-preview-header": "_file-preview-header_m0qyk_139",
|
|
4
|
+
"file-preview-info": "_file-preview-info_m0qyk_148",
|
|
5
|
+
"file-preview-icon": "_file-preview-icon_m0qyk_156",
|
|
6
|
+
"file-preview-name": "_file-preview-name_m0qyk_161",
|
|
7
|
+
"file-preview-size": "_file-preview-size_m0qyk_168",
|
|
8
|
+
"file-preview-body": "_file-preview-body_m0qyk_174",
|
|
9
|
+
"file-preview-iframe": "_file-preview-iframe_m0qyk_178",
|
|
10
|
+
"file-preview-media-wrap": "_file-preview-media-wrap_m0qyk_186",
|
|
11
|
+
"file-preview-image": "_file-preview-image_m0qyk_192",
|
|
12
|
+
"file-preview-video": "_file-preview-video_m0qyk_198",
|
|
13
|
+
"file-preview-audio-wrap": "_file-preview-audio-wrap_m0qyk_204",
|
|
14
|
+
"file-preview-audio": "_file-preview-audio_m0qyk_204",
|
|
15
|
+
"file-preview-office-wrap": "_file-preview-office-wrap_m0qyk_216",
|
|
16
|
+
"file-preview-office-spin": "_file-preview-office-spin_m0qyk_222",
|
|
17
|
+
"file-preview-office-inner": "_file-preview-office-inner_m0qyk_233",
|
|
18
|
+
"file-preview-text": "_file-preview-text_m0qyk_240"
|
|
18
19
|
};
|
|
19
20
|
export {
|
|
20
21
|
e as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,6 +7,8 @@ export interface FilePreviewLinkProps {
|
|
|
7
7
|
onDownload?: (file: FileDisplayItem) => void;
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
showType?: boolean;
|
|
10
|
+
/** 文件名超长时换行展示(默认单行省略) */
|
|
11
|
+
nameWrap?: boolean;
|
|
10
12
|
className?: string;
|
|
11
13
|
}
|
|
12
14
|
declare const FilePreviewLink: React.FC<FilePreviewLinkProps>;
|
|
@@ -1,61 +1,74 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { normalizeFileDisplayItem as
|
|
3
|
-
import
|
|
4
|
-
import { useState as
|
|
1
|
+
import { jsxs as a, jsx as l, Fragment as y } from "react/jsx-runtime";
|
|
2
|
+
import { normalizeFileDisplayItem as u, getFileIcon as o, getFileTypeName as c } from "../fileDisplay.js";
|
|
3
|
+
import F from "../FilePreviewModal/index.js";
|
|
4
|
+
import { useState as T } from "react";
|
|
5
5
|
import i from "./style.module.scss.js";
|
|
6
|
-
import
|
|
7
|
-
const
|
|
8
|
-
file:
|
|
9
|
-
url:
|
|
10
|
-
downloadUrl:
|
|
6
|
+
import r from "classnames";
|
|
7
|
+
const P = ({
|
|
8
|
+
file: v,
|
|
9
|
+
url: s,
|
|
10
|
+
downloadUrl: w,
|
|
11
11
|
onDownload: d,
|
|
12
|
-
disabled:
|
|
13
|
-
showType:
|
|
14
|
-
|
|
12
|
+
disabled: k = !1,
|
|
13
|
+
showType: m = !0,
|
|
14
|
+
nameWrap: n = !1,
|
|
15
|
+
className: p
|
|
15
16
|
}) => {
|
|
16
|
-
const [
|
|
17
|
-
|
|
17
|
+
const [N, t] = T(!1), e = u(v), f = r(
|
|
18
|
+
i["file-preview-link-name"],
|
|
19
|
+
n && i["file-preview-link-name-wrap"]
|
|
20
|
+
);
|
|
21
|
+
return k ? /* @__PURE__ */ a(
|
|
18
22
|
"span",
|
|
19
23
|
{
|
|
20
|
-
className:
|
|
24
|
+
className: r(
|
|
25
|
+
i["file-preview-link-disabled"],
|
|
26
|
+
p,
|
|
27
|
+
n && i["file-preview-link-wrap"]
|
|
28
|
+
),
|
|
21
29
|
title: e.name,
|
|
22
30
|
children: [
|
|
23
|
-
/* @__PURE__ */ l("span", { className: i["file-preview-link-inner"], children:
|
|
24
|
-
/* @__PURE__ */ l("span", { className:
|
|
25
|
-
|
|
31
|
+
/* @__PURE__ */ l("span", { className: i["file-preview-link-inner"], children: o(e.name, e.mimeType) }),
|
|
32
|
+
/* @__PURE__ */ l("span", { className: f, children: e.name }),
|
|
33
|
+
m && /* @__PURE__ */ l("span", { className: i["file-preview-link-type"], children: c(e.name, e.mimeType) })
|
|
26
34
|
]
|
|
27
35
|
}
|
|
28
|
-
) : /* @__PURE__ */
|
|
29
|
-
/* @__PURE__ */
|
|
36
|
+
) : /* @__PURE__ */ a(y, { children: [
|
|
37
|
+
/* @__PURE__ */ a(
|
|
30
38
|
"a",
|
|
31
39
|
{
|
|
32
|
-
className:
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
className: r(
|
|
41
|
+
"file-preview-link",
|
|
42
|
+
i["file-preview-link"],
|
|
43
|
+
p,
|
|
44
|
+
n && i["file-preview-link-wrap"]
|
|
45
|
+
),
|
|
46
|
+
onClick: (h) => {
|
|
47
|
+
h.preventDefault(), t(!0);
|
|
35
48
|
},
|
|
36
|
-
href:
|
|
49
|
+
href: s ?? e.url ?? "#",
|
|
37
50
|
title: e.name,
|
|
38
51
|
children: [
|
|
39
|
-
/* @__PURE__ */ l("span", { className: i["file-preview-link-inner"], children:
|
|
40
|
-
/* @__PURE__ */ l("span", { className:
|
|
41
|
-
|
|
52
|
+
/* @__PURE__ */ l("span", { className: i["file-preview-link-inner"], children: o(e.name, e.mimeType) }),
|
|
53
|
+
/* @__PURE__ */ l("span", { className: f, children: e.name }),
|
|
54
|
+
m && /* @__PURE__ */ l("span", { className: i["file-preview-link-type"], children: c(e.name, e.mimeType) })
|
|
42
55
|
]
|
|
43
56
|
}
|
|
44
57
|
),
|
|
45
58
|
/* @__PURE__ */ l(
|
|
46
|
-
|
|
59
|
+
F,
|
|
47
60
|
{
|
|
48
|
-
open:
|
|
61
|
+
open: N,
|
|
49
62
|
file: e,
|
|
50
|
-
url:
|
|
51
|
-
downloadUrl:
|
|
63
|
+
url: s,
|
|
64
|
+
downloadUrl: w,
|
|
52
65
|
onDownload: d,
|
|
53
|
-
onClose: () =>
|
|
66
|
+
onClose: () => t(!1)
|
|
54
67
|
}
|
|
55
68
|
)
|
|
56
69
|
] });
|
|
57
70
|
};
|
|
58
71
|
export {
|
|
59
|
-
|
|
72
|
+
P as default
|
|
60
73
|
};
|
|
61
74
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/File/FilePreviewLink/index.tsx"],"sourcesContent":["import type { FileDisplayItem } from '../types';\nimport { getFileIcon, getFileTypeName, normalizeFileDisplayItem } from '../fileDisplay';\nimport FilePreviewModal from '../FilePreviewModal';\nimport React, { useState } from 'react';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\nexport interface FilePreviewLinkProps {\n file: FileDisplayItem;\n url?: string;\n downloadUrl?: string;\n onDownload?: (file: FileDisplayItem) => void;\n disabled?: boolean;\n showType?: boolean;\n className?: string;\n}\n\nconst FilePreviewLink: React.FC<FilePreviewLinkProps> = ({\n file,\n url,\n downloadUrl,\n onDownload,\n disabled = false,\n showType = true,\n className,\n}) => {\n const [open, setOpen] = useState(false);\n const resolvedFile = normalizeFileDisplayItem(file);\n\n if (disabled) {\n return (\n <span\n className={classNames(styles['file-preview-link-disabled']
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/File/FilePreviewLink/index.tsx"],"sourcesContent":["import type { FileDisplayItem } from '../types';\nimport { getFileIcon, getFileTypeName, normalizeFileDisplayItem } from '../fileDisplay';\nimport FilePreviewModal from '../FilePreviewModal';\nimport React, { useState } from 'react';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\nexport interface FilePreviewLinkProps {\n file: FileDisplayItem;\n url?: string;\n downloadUrl?: string;\n onDownload?: (file: FileDisplayItem) => void;\n disabled?: boolean;\n showType?: boolean;\n /** 文件名超长时换行展示(默认单行省略) */\n nameWrap?: boolean;\n className?: string;\n}\n\nconst FilePreviewLink: React.FC<FilePreviewLinkProps> = ({\n file,\n url,\n downloadUrl,\n onDownload,\n disabled = false,\n showType = true,\n nameWrap = false,\n className,\n}) => {\n const [open, setOpen] = useState(false);\n const resolvedFile = normalizeFileDisplayItem(file);\n\n const nameClassName = classNames(\n styles['file-preview-link-name'],\n nameWrap && styles['file-preview-link-name-wrap'],\n );\n\n if (disabled) {\n return (\n <span\n className={classNames(\n styles['file-preview-link-disabled'],\n className,\n nameWrap && styles['file-preview-link-wrap'],\n )}\n title={resolvedFile.name}\n >\n <span className={styles['file-preview-link-inner']}>\n {getFileIcon(resolvedFile.name, resolvedFile.mimeType)}\n </span>\n <span className={nameClassName}>{resolvedFile.name}</span>\n {showType && (\n <span className={styles['file-preview-link-type']}>\n {getFileTypeName(resolvedFile.name, resolvedFile.mimeType)}\n </span>\n )}\n </span>\n );\n }\n\n return (\n <>\n <a\n className={classNames(\n 'file-preview-link',\n styles['file-preview-link'],\n className,\n nameWrap && styles['file-preview-link-wrap'],\n )}\n onClick={(e) => {\n e.preventDefault();\n setOpen(true);\n }}\n href={url ?? resolvedFile.url ?? '#'}\n title={resolvedFile.name}\n >\n <span className={styles['file-preview-link-inner']}>\n {getFileIcon(resolvedFile.name, resolvedFile.mimeType)}\n </span>\n <span className={nameClassName}>{resolvedFile.name}</span>\n {showType && (\n <span className={styles['file-preview-link-type']}>\n {getFileTypeName(resolvedFile.name, resolvedFile.mimeType)}\n </span>\n )}\n </a>\n <FilePreviewModal\n open={open}\n file={resolvedFile}\n url={url}\n downloadUrl={downloadUrl}\n onDownload={onDownload}\n onClose={() => setOpen(false)}\n />\n </>\n );\n};\n\nexport default FilePreviewLink;\n"],"names":["FilePreviewLink","file","url","downloadUrl","onDownload","disabled","showType","nameWrap","className","open","setOpen","useState","resolvedFile","normalizeFileDisplayItem","nameClassName","classNames","styles","jsxs","jsx","getFileTypeName","Fragment","e","FilePreviewModal"],"mappings":";;;;;;AAmBA,MAAMA,IAAkD,CAAC;AAAA,EACvD,MAAAC;AAAA,EACA,KAAAC;AAAA,EACA,aAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,UAAAC,IAAW;AAAA,EACX,UAAAC,IAAW;AAAA,EACX,WAAAC;AACF,MAAM;AACJ,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAeC,EAAyBZ,CAAI,GAE5Ca,IAAgBC;AAAA,IACpBC,EAAO,wBAAwB;AAAA,IAC/BT,KAAYS,EAAO,6BAA6B;AAAA,EAAA;AAGlD,SAAIX,IAEA,gBAAAY;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWF;AAAA,QACTC,EAAO,4BAA4B;AAAA,QACnCR;AAAA,QACAD,KAAYS,EAAO,wBAAwB;AAAA,MAAA;AAAA,MAE7C,OAAOJ,EAAa;AAAA,MAEpB,UAAA;AAAA,QAAA,gBAAAM,EAAC,QAAA,EAAK,WAAWF,EAAO,yBAAyB,GAC9C,YAAYJ,EAAa,MAAMA,EAAa,QAAQ,EAAA,CACvD;AAAA,QACA,gBAAAM,EAAC,QAAA,EAAK,WAAWJ,GAAgB,YAAa,MAAK;AAAA,QAClDR,KACC,gBAAAY,EAAC,QAAA,EAAK,WAAWF,EAAO,wBAAwB,GAC7C,UAAAG,EAAgBP,EAAa,MAAMA,EAAa,QAAQ,EAAA,CAC3D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,IAON,gBAAAK,EAAAG,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAH;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWF;AAAA,UACT;AAAA,UACAC,EAAO,mBAAmB;AAAA,UAC1BR;AAAA,UACAD,KAAYS,EAAO,wBAAwB;AAAA,QAAA;AAAA,QAE7C,SAAS,CAACK,MAAM;AACd,UAAAA,EAAE,eAAA,GACFX,EAAQ,EAAI;AAAA,QACd;AAAA,QACA,MAAMR,KAAOU,EAAa,OAAO;AAAA,QACjC,OAAOA,EAAa;AAAA,QAEpB,UAAA;AAAA,UAAA,gBAAAM,EAAC,QAAA,EAAK,WAAWF,EAAO,yBAAyB,GAC9C,YAAYJ,EAAa,MAAMA,EAAa,QAAQ,EAAA,CACvD;AAAA,UACA,gBAAAM,EAAC,QAAA,EAAK,WAAWJ,GAAgB,YAAa,MAAK;AAAA,UAClDR,KACC,gBAAAY,EAAC,QAAA,EAAK,WAAWF,EAAO,wBAAwB,GAC7C,UAAAG,EAAgBP,EAAa,MAAMA,EAAa,QAAQ,EAAA,CAC3D;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGJ,gBAAAM;AAAA,MAACI;AAAA,MAAA;AAAA,QACC,MAAAb;AAAA,QACA,MAAMG;AAAA,QACN,KAAAV;AAAA,QACA,aAAAC;AAAA,QACA,YAAAC;AAAA,QACA,SAAS,MAAMM,EAAQ,EAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAC9B,GACF;AAEJ;"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const e = {
|
|
2
|
-
"file-preview-link": "_file-preview-
|
|
3
|
-
"file-preview-link-
|
|
4
|
-
"file-preview-link-
|
|
5
|
-
"file-preview-link-
|
|
6
|
-
"file-preview-link-
|
|
2
|
+
"file-preview-link": "_file-preview-link_1q16r_1",
|
|
3
|
+
"file-preview-link-wrap": "_file-preview-link-wrap_1q16r_12",
|
|
4
|
+
"file-preview-link-disabled": "_file-preview-link-disabled_1q16r_17",
|
|
5
|
+
"file-preview-link-inner": "_file-preview-link-inner_1q16r_26",
|
|
6
|
+
"file-preview-link-name": "_file-preview-link-name_1q16r_30",
|
|
7
|
+
"file-preview-link-name-wrap": "_file-preview-link-name-wrap_1q16r_36",
|
|
8
|
+
"file-preview-link-type": "_file-preview-link-type_1q16r_44"
|
|
7
9
|
};
|
|
8
10
|
export {
|
|
9
11
|
e as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import r from "classnames";
|
|
3
|
+
import { parseLlmText as o } from "../parseLlmText.js";
|
|
4
|
+
import t from "./style.module.scss.js";
|
|
5
|
+
const p = {
|
|
6
|
+
causes: "◆",
|
|
7
|
+
suggestions: "✓",
|
|
8
|
+
summary: "●"
|
|
9
|
+
}, y = ({
|
|
10
|
+
text: m = "",
|
|
11
|
+
loading: d,
|
|
12
|
+
className: i
|
|
13
|
+
}) => {
|
|
14
|
+
const s = o(m);
|
|
15
|
+
return d || s.loading ? /* @__PURE__ */ l("div", { className: r("llm-formatted-text", t["llm-formatted-text"], t["is-loading"], i), children: [
|
|
16
|
+
/* @__PURE__ */ e("span", { className: t["ft-spinner"], "aria-hidden": !0 }),
|
|
17
|
+
/* @__PURE__ */ e("span", { children: m || "正在生成..." })
|
|
18
|
+
] }) : s.summary || s.sections.length > 0 ? /* @__PURE__ */ l("div", { className: r("llm-formatted-text", t["llm-formatted-text"], i), children: [
|
|
19
|
+
s.summary ? /* @__PURE__ */ e("p", { className: t["ft-summary"], children: s.summary }) : null,
|
|
20
|
+
s.sections.map((a) => /* @__PURE__ */ l(
|
|
21
|
+
"section",
|
|
22
|
+
{
|
|
23
|
+
className: r(t["ft-section"], t[`ft-${a.type}`]),
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ l("h4", { className: t["ft-section-title"], children: [
|
|
26
|
+
/* @__PURE__ */ e("span", { className: t["ft-section-icon"], "aria-hidden": !0, children: p[a.type] || "•" }),
|
|
27
|
+
a.title
|
|
28
|
+
] }),
|
|
29
|
+
a.items.length > 1 ? /* @__PURE__ */ e("ul", { className: t["ft-list"], children: a.items.map((c, n) => /* @__PURE__ */ l("li", { children: [
|
|
30
|
+
/* @__PURE__ */ e("span", { className: t["ft-num"], children: n + 1 }),
|
|
31
|
+
/* @__PURE__ */ e("span", { className: t["ft-item-text"], children: c })
|
|
32
|
+
] }, n)) }) : /* @__PURE__ */ e("p", { className: t["ft-paragraph"], children: a.items[0] })
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
`${a.type}-${a.title}`
|
|
36
|
+
))
|
|
37
|
+
] }) : /* @__PURE__ */ e("div", { className: r("llm-formatted-text", t["llm-formatted-text"], i), children: /* @__PURE__ */ e("p", { className: t["ft-paragraph"], children: m }) });
|
|
38
|
+
};
|
|
39
|
+
export {
|
|
40
|
+
y as default
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/LlmFormattedText/LlmFormattedText/index.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport React from 'react';\nimport { parseLlmText } from '../parseLlmText';\nimport styles from './style.module.scss';\n\nconst SECTION_ICONS: Record<string, string> = {\n causes: '◆',\n suggestions: '✓',\n summary: '●',\n};\n\nexport interface LlmFormattedTextProps {\n text?: string;\n loading?: boolean;\n className?: string;\n}\n\nconst LlmFormattedText: React.FC<LlmFormattedTextProps> = ({\n text = '',\n loading: loadingProp,\n className,\n}) => {\n const parsed = parseLlmText(text);\n const loading = loadingProp || parsed.loading;\n\n if (loading) {\n return (\n <div className={classNames('llm-formatted-text', styles['llm-formatted-text'], styles['is-loading'], className)}>\n <span className={styles['ft-spinner']} aria-hidden />\n <span>{text || '正在生成...'}</span>\n </div>\n );\n }\n\n const hasStructure = parsed.summary || parsed.sections.length > 0;\n if (!hasStructure) {\n return (\n <div className={classNames('llm-formatted-text', styles['llm-formatted-text'], className)}>\n <p className={styles['ft-paragraph']}>{text}</p>\n </div>\n );\n }\n\n return (\n <div className={classNames('llm-formatted-text', styles['llm-formatted-text'], className)}>\n {parsed.summary ? <p className={styles['ft-summary']}>{parsed.summary}</p> : null}\n {parsed.sections.map((sec: { type: string; title: string; items: string[] }) => (\n <section\n key={`${sec.type}-${sec.title}`}\n className={classNames(styles['ft-section'], styles[`ft-${sec.type}`])}\n >\n <h4 className={styles['ft-section-title']}>\n <span className={styles['ft-section-icon']} aria-hidden>\n {SECTION_ICONS[sec.type] || '•'}\n </span>\n {sec.title}\n </h4>\n {sec.items.length > 1 ? (\n <ul className={styles['ft-list']}>\n {sec.items.map((item: string, i: number) => (\n <li key={i}>\n <span className={styles['ft-num']}>{i + 1}</span>\n <span className={styles['ft-item-text']}>{item}</span>\n </li>\n ))}\n </ul>\n ) : (\n <p className={styles['ft-paragraph']}>{sec.items[0]}</p>\n )}\n </section>\n ))}\n </div>\n );\n};\n\nexport default LlmFormattedText;\n"],"names":["SECTION_ICONS","LlmFormattedText","text","loadingProp","className","parsed","parseLlmText","jsxs","classNames","styles","jsx","sec","item","i"],"mappings":";;;;AAKA,MAAMA,IAAwC;AAAA,EAC5C,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,SAAS;AACX,GAQMC,IAAoD,CAAC;AAAA,EACzD,MAAAC,IAAO;AAAA,EACP,SAASC;AAAA,EACT,WAAAC;AACF,MAAM;AACJ,QAAMC,IAASC,EAAaJ,CAAI;AAGhC,SAFgBC,KAAeE,EAAO,UAIlC,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAW,sBAAsBC,EAAO,oBAAoB,GAAGA,EAAO,YAAY,GAAGL,CAAS,GAC5G,UAAA;AAAA,IAAA,gBAAAM,EAAC,UAAK,WAAWD,EAAO,YAAY,GAAG,eAAW,IAAC;AAAA,IACnD,gBAAAC,EAAC,QAAA,EAAM,UAAAR,KAAQ,UAAA,CAAU;AAAA,EAAA,GAC3B,IAIiBG,EAAO,WAAWA,EAAO,SAAS,SAAS,IAU9D,gBAAAE,EAAC,SAAI,WAAWC,EAAW,sBAAsBC,EAAO,oBAAoB,GAAGL,CAAS,GACrF,UAAA;AAAA,IAAAC,EAAO,4BAAW,KAAA,EAAE,WAAWI,EAAO,YAAY,GAAI,UAAAJ,EAAO,QAAA,CAAQ,IAAO;AAAA,IAC5EA,EAAO,SAAS,IAAI,CAACM,MACpB,gBAAAJ;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAWC,EAAWC,EAAO,YAAY,GAAGA,EAAO,MAAME,EAAI,IAAI,EAAE,CAAC;AAAA,QAEpE,UAAA;AAAA,UAAA,gBAAAJ,EAAC,MAAA,EAAG,WAAWE,EAAO,kBAAkB,GACtC,UAAA;AAAA,YAAA,gBAAAC,EAAC,QAAA,EAAK,WAAWD,EAAO,iBAAiB,GAAG,eAAW,IACpD,UAAAT,EAAcW,EAAI,IAAI,KAAK,IAAA,CAC9B;AAAA,YACCA,EAAI;AAAA,UAAA,GACP;AAAA,UACCA,EAAI,MAAM,SAAS,IAClB,gBAAAD,EAAC,QAAG,WAAWD,EAAO,SAAS,GAC5B,YAAI,MAAM,IAAI,CAACG,GAAcC,wBAC3B,MAAA,EACC,UAAA;AAAA,YAAA,gBAAAH,EAAC,UAAK,WAAWD,EAAO,QAAQ,GAAI,cAAI,GAAE;AAAA,8BACzC,QAAA,EAAK,WAAWA,EAAO,cAAc,GAAI,UAAAG,EAAA,CAAK;AAAA,UAAA,EAAA,GAFxCC,CAGT,CACD,EAAA,CACH,IAEA,gBAAAH,EAAC,KAAA,EAAE,WAAWD,EAAO,cAAc,GAAI,UAAAE,EAAI,MAAM,CAAC,EAAA,CAAE;AAAA,QAAA;AAAA,MAAA;AAAA,MAnBjD,GAAGA,EAAI,IAAI,IAAIA,EAAI,KAAK;AAAA,IAAA,CAsBhC;AAAA,EAAA,GACH,sBAlCG,OAAA,EAAI,WAAWH,EAAW,sBAAsBC,EAAO,oBAAoB,GAAGL,CAAS,GACtF,4BAAC,KAAA,EAAE,WAAWK,EAAO,cAAc,GAAI,aAAK,GAC9C;AAkCN;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const t = {
|
|
2
|
+
"llm-formatted-text": "_llm-formatted-text_1mo0r_1",
|
|
3
|
+
"is-loading": "_is-loading_1mo0r_7",
|
|
4
|
+
"ft-spinner": "_ft-spinner_1mo0r_14",
|
|
5
|
+
"llm-ft-spin": "_llm-ft-spin_1mo0r_1",
|
|
6
|
+
"ft-summary": "_ft-summary_1mo0r_28",
|
|
7
|
+
"ft-section": "_ft-section_1mo0r_33",
|
|
8
|
+
"ft-section-title": "_ft-section-title_1mo0r_37",
|
|
9
|
+
"ft-section-icon": "_ft-section-icon_1mo0r_46",
|
|
10
|
+
"ft-list": "_ft-list_1mo0r_50",
|
|
11
|
+
"ft-num": "_ft-num_1mo0r_62",
|
|
12
|
+
"ft-paragraph": "_ft-paragraph_1mo0r_69"
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
t as default
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=style.module.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** 将 LLM 纯文本解析为带层级的内容块 */
|
|
2
|
+
export type LlmTextSection = {
|
|
3
|
+
type: string;
|
|
4
|
+
title: string;
|
|
5
|
+
items: string[];
|
|
6
|
+
};
|
|
7
|
+
export type ParsedLlmText = {
|
|
8
|
+
summary: string;
|
|
9
|
+
sections: LlmTextSection[];
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare function parseLlmText(text: string): ParsedLlmText;
|
|
13
|
+
/** 供静态 HTML 报告使用的排版 HTML */
|
|
14
|
+
export declare function formatLlmTextToHtml(text: string): string;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const g = [
|
|
2
|
+
{ type: "causes", titles: ["可能原因", "原因分析", "主要原因", "异常原因"] },
|
|
3
|
+
{ type: "suggestions", titles: ["建议", "改进建议", "处置建议", "应对措施", "整改建议"] },
|
|
4
|
+
{ type: "summary", titles: ["异常说明", "情况说明", "分析结论", "结论"] }
|
|
5
|
+
], d = new RegExp("(?:^|\\s)(?:[((]?\\d+[))]|[①②③④⑤⑥⑦⑧⑨⑩⑪⑫]|(?<!\\d)\\d+[、..])(?=\\s*[^\\d])", "g");
|
|
6
|
+
function h(l) {
|
|
7
|
+
return String(l || "").replace(/\r\n/g, `
|
|
8
|
+
`).replace(/[ \t]+\n/g, `
|
|
9
|
+
`).replace(/\n{3,}/g, `
|
|
10
|
+
|
|
11
|
+
`).trim();
|
|
12
|
+
}
|
|
13
|
+
function x(l) {
|
|
14
|
+
const t = l.trim();
|
|
15
|
+
if (!t) return [];
|
|
16
|
+
const i = t.split(d).map((n) => n.trim()).filter(Boolean);
|
|
17
|
+
if (i.length > 1) return i;
|
|
18
|
+
const e = t.split(/\n+/).map((n) => n.replace(/^[((]?\d+[))]\s*|^[①②③④⑤⑥⑦⑧⑨⑩]\s*|\d+[、..]\s*/, "").trim()).filter(Boolean);
|
|
19
|
+
return e.length > 1 ? e : [t];
|
|
20
|
+
}
|
|
21
|
+
function y(l) {
|
|
22
|
+
const t = h(l);
|
|
23
|
+
if (!t) return { summary: "", sections: [] };
|
|
24
|
+
if (/^(正在|思考中|分析中|加载)/.test(t) && t.length < 40)
|
|
25
|
+
return { summary: t, sections: [], loading: !0 };
|
|
26
|
+
const i = [];
|
|
27
|
+
let e = "";
|
|
28
|
+
const n = [];
|
|
29
|
+
for (const s of g)
|
|
30
|
+
for (const r of s.titles) {
|
|
31
|
+
const p = new RegExp(`(${r})[::\\s]*`, "g");
|
|
32
|
+
let c;
|
|
33
|
+
for (; (c = p.exec(t)) !== null; )
|
|
34
|
+
n.push({ type: s.type, title: r, index: c.index, len: c[0].length });
|
|
35
|
+
}
|
|
36
|
+
if (n.sort((s, r) => s.index - r.index), n.length === 0)
|
|
37
|
+
return { summary: t, sections: [] };
|
|
38
|
+
const a = n[0];
|
|
39
|
+
a.index > 0 && (e = t.slice(0, a.index).replace(/[::\s]+$/, "").trim());
|
|
40
|
+
for (let s = 0; s < n.length; s += 1) {
|
|
41
|
+
const r = n[s], p = r.index + r.len, c = n[s + 1], u = c ? c.index : t.length, m = t.slice(p, u).trim(), f = x(m);
|
|
42
|
+
i.push({
|
|
43
|
+
type: r.type,
|
|
44
|
+
title: r.title,
|
|
45
|
+
items: f.length ? f : [m]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!e && i.length) {
|
|
49
|
+
const s = a.index;
|
|
50
|
+
s > 80 && (e = t.slice(0, s).trim());
|
|
51
|
+
}
|
|
52
|
+
return !e && i.length === 0 && (e = t), { summary: e, sections: i };
|
|
53
|
+
}
|
|
54
|
+
function o(l) {
|
|
55
|
+
return l.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
56
|
+
}
|
|
57
|
+
function $(l) {
|
|
58
|
+
const t = y(l);
|
|
59
|
+
if (t.loading)
|
|
60
|
+
return `<p class="ft-loading">${o(t.summary)}</p>`;
|
|
61
|
+
const i = [];
|
|
62
|
+
t.summary && i.push(`<p class="ft-summary">${o(t.summary)}</p>`);
|
|
63
|
+
for (const e of t.sections) {
|
|
64
|
+
const n = `ft-section ft-${e.type}`, a = e.items.length > 1 ? `<ul class="ft-list">${e.items.map(
|
|
65
|
+
(s, r) => `<li><span class="ft-num">${r + 1}</span><span class="ft-item-text">${o(s)}</span></li>`
|
|
66
|
+
).join("")}</ul>` : `<p class="ft-paragraph">${o(e.items[0] || "")}</p>`;
|
|
67
|
+
i.push(
|
|
68
|
+
`<section class="${n}"><h4 class="ft-section-title">${o(e.title)}</h4>${a}</section>`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return i.length ? `<div class="formatted-text">${i.join("")}</div>` : `<p class="ft-paragraph">${o(l || "")}</p>`;
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
$ as formatLlmTextToHtml,
|
|
75
|
+
y as parseLlmText
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=parseLlmText.js.map
|