@hkyhy/marsun-components-core 0.1.23 → 0.1.25
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/AgentHub/Chat/utils/index.d.ts +2 -0
- package/dist/components/AgentHub/Chat/utils/smoothScroll.js +51 -0
- package/dist/components/AgentHub/Chat/utils/smoothScroll.js.map +1 -0
- package/dist/components/File/FilePreview/FilePreviewContent.js +11 -12
- package/dist/components/File/FilePreview/FilePreviewContent.js.map +1 -1
- package/dist/components/Filter/FilterSelect/index.d.ts +4 -2
- package/dist/components/Filter/FilterSelect/index.js +253 -157
- package/dist/components/Filter/FilterSelect/index.js.map +1 -1
- package/dist/components/Filter/FilterSelect/style.module.scss.js +14 -12
- package/dist/components/Filter/FilterSelect/style.module.scss.js.map +1 -1
- package/dist/components/Form/index.d.ts +6 -0
- package/dist/components/Form/kneFormInfo.d.ts +47 -0
- package/dist/components/Form/kneFormInfo.js +23 -0
- package/dist/components/Form/kneFormInfo.js.map +1 -0
- package/dist/components/Form/kneReactForm.d.ts +8 -0
- package/dist/components/Layout/PageSpin/index.js +5 -5
- package/dist/components/Layout/PageSpin/index.js.map +1 -1
- package/dist/components/Table/Table.d.ts +8 -0
- package/dist/components/Table/Table.js +39 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Table/index.d.ts +2 -0
- package/dist/components/Table/style.module.scss.js +7 -0
- package/dist/components/Table/style.module.scss.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +379 -332
- package/dist/index.js.map +1 -1
- package/dist/marsun-components-core.css +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/theme/theme.js +8 -6
- package/dist/theme/theme.js.map +1 -1
- package/dist/theme/tokens.css +12 -0
- package/dist/utils/authRedirect.d.ts +17 -4
- package/dist/utils/authRedirect.js +39 -20
- package/dist/utils/authRedirect.js.map +1 -1
- package/dist/utils/createMarsunRequest.d.ts +2 -0
- package/dist/utils/createMarsunRequest.js +20 -18
- package/dist/utils/createMarsunRequest.js.map +1 -1
- package/package.json +4 -1
|
@@ -3,3 +3,5 @@ export { hasCitationMarkers, normalizeAssistantMarkdown, normalizeDisplayText, p
|
|
|
3
3
|
export type { ParsedAssistantContent } from './messageContent';
|
|
4
4
|
export { sanitizeMermaidChart, stripProseFromMermaid } from './sanitizeMermaidChart';
|
|
5
5
|
export { extractCitations, formatSessionTime, getSessionDisplayName, isWelcomeOnlyMessages, parseSessionMessages, toDisplayMessages, } from './sessionMessages';
|
|
6
|
+
export { animateScrollFromTopToBottom, animateScrollTo, getScrollBottom } from './smoothScroll';
|
|
7
|
+
export type { AnimateScrollOptions } from './smoothScroll';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const d = (t) => 1 - (1 - t) ** 5, T = (t, n, o = {}) => {
|
|
2
|
+
const { minDuration: i = 420, maxDuration: s = 880, msPerPixel: a = 0.32 } = o, r = Math.max(0, t.scrollHeight - t.clientHeight), c = Math.min(Math.max(0, n), r), l = t.scrollTop, m = c - l;
|
|
3
|
+
if (Math.abs(m) < 1)
|
|
4
|
+
return t.scrollTop = c, () => {
|
|
5
|
+
};
|
|
6
|
+
const f = Math.min(Math.max(Math.abs(m) * a, i), s), g = performance.now();
|
|
7
|
+
let e = 0, u = !1;
|
|
8
|
+
const h = (M) => {
|
|
9
|
+
if (u) return;
|
|
10
|
+
const p = Math.min((M - g) / f, 1);
|
|
11
|
+
t.scrollTop = l + m * d(p), p < 1 && (e = requestAnimationFrame(h));
|
|
12
|
+
};
|
|
13
|
+
return e = requestAnimationFrame(h), () => {
|
|
14
|
+
u = !0, cancelAnimationFrame(e);
|
|
15
|
+
};
|
|
16
|
+
}, x = (t) => Math.max(0, t.scrollHeight - t.clientHeight), F = (t, n = {}) => {
|
|
17
|
+
const o = [];
|
|
18
|
+
t.scrollTop = 0;
|
|
19
|
+
const i = () => {
|
|
20
|
+
o.push(
|
|
21
|
+
T(t, x(t), {
|
|
22
|
+
minDuration: 460,
|
|
23
|
+
maxDuration: 920,
|
|
24
|
+
msPerPixel: 0.34,
|
|
25
|
+
...n
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
const a = window.setTimeout(() => {
|
|
29
|
+
const r = x(t);
|
|
30
|
+
r - t.scrollTop > 6 && o.push(
|
|
31
|
+
T(t, r, {
|
|
32
|
+
minDuration: 180,
|
|
33
|
+
maxDuration: 320,
|
|
34
|
+
msPerPixel: 0.2
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}, 120);
|
|
38
|
+
o.push(() => window.clearTimeout(a));
|
|
39
|
+
}, s = requestAnimationFrame(() => {
|
|
40
|
+
requestAnimationFrame(i);
|
|
41
|
+
});
|
|
42
|
+
return () => {
|
|
43
|
+
cancelAnimationFrame(s), o.forEach((a) => a());
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
F as animateScrollFromTopToBottom,
|
|
48
|
+
T as animateScrollTo,
|
|
49
|
+
x as getScrollBottom
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=smoothScroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoothScroll.js","sources":["../../../../../src/components/AgentHub/Chat/utils/smoothScroll.ts"],"sourcesContent":["export interface AnimateScrollOptions {\n minDuration?: number;\n maxDuration?: number;\n msPerPixel?: number;\n}\n\nconst easeOutQuint = (progress: number) => 1 - (1 - progress) ** 5;\n\n/**\n * Smoothly scroll an element with a custom ease-out curve (softer than native smooth).\n */\nexport const animateScrollTo = (\n element: HTMLElement,\n targetTop: number,\n options: AnimateScrollOptions = {},\n): (() => void) => {\n const { minDuration = 420, maxDuration = 880, msPerPixel = 0.32 } = options;\n\n const maxTop = Math.max(0, element.scrollHeight - element.clientHeight);\n const clampedTarget = Math.min(Math.max(0, targetTop), maxTop);\n const startTop = element.scrollTop;\n const distance = clampedTarget - startTop;\n\n if (Math.abs(distance) < 1) {\n element.scrollTop = clampedTarget;\n return () => {};\n }\n\n const duration = Math.min(Math.max(Math.abs(distance) * msPerPixel, minDuration), maxDuration);\n const startTime = performance.now();\n let rafId = 0;\n let cancelled = false;\n\n const step = (now: number) => {\n if (cancelled) return;\n\n const progress = Math.min((now - startTime) / duration, 1);\n element.scrollTop = startTop + distance * easeOutQuint(progress);\n\n if (progress < 1) {\n rafId = requestAnimationFrame(step);\n }\n };\n\n rafId = requestAnimationFrame(step);\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n };\n};\n\nexport const getScrollBottom = (element: HTMLElement) =>\n Math.max(0, element.scrollHeight - element.clientHeight);\n\n/**\n * Session switch: reset to top, then ease to bottom; optional soft correction after layout shifts.\n */\nexport const animateScrollFromTopToBottom = (\n element: HTMLElement,\n options: AnimateScrollOptions = {},\n): (() => void) => {\n const cleanups: Array<() => void> = [];\n\n element.scrollTop = 0;\n\n const start = () => {\n cleanups.push(\n animateScrollTo(element, getScrollBottom(element), {\n minDuration: 460,\n maxDuration: 920,\n msPerPixel: 0.34,\n ...options,\n }),\n );\n\n const correctionTimer = window.setTimeout(() => {\n const bottom = getScrollBottom(element);\n const remaining = bottom - element.scrollTop;\n if (remaining > 6) {\n cleanups.push(\n animateScrollTo(element, bottom, {\n minDuration: 180,\n maxDuration: 320,\n msPerPixel: 0.2,\n }),\n );\n }\n }, 120);\n\n cleanups.push(() => window.clearTimeout(correctionTimer));\n };\n\n const raf = requestAnimationFrame(() => {\n requestAnimationFrame(start);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n cleanups.forEach((cleanup) => cleanup());\n };\n};\n"],"names":["easeOutQuint","progress","animateScrollTo","element","targetTop","options","minDuration","maxDuration","msPerPixel","maxTop","clampedTarget","startTop","distance","duration","startTime","rafId","cancelled","step","now","getScrollBottom","animateScrollFromTopToBottom","cleanups","start","correctionTimer","bottom","raf","cleanup"],"mappings":"AAMA,MAAMA,IAAe,CAACC,MAAqB,KAAK,IAAIA,MAAa,GAKpDC,IAAkB,CAC7BC,GACAC,GACAC,IAAgC,CAAA,MACf;AACjB,QAAM,EAAE,aAAAC,IAAc,KAAK,aAAAC,IAAc,KAAK,YAAAC,IAAa,SAASH,GAE9DI,IAAS,KAAK,IAAI,GAAGN,EAAQ,eAAeA,EAAQ,YAAY,GAChEO,IAAgB,KAAK,IAAI,KAAK,IAAI,GAAGN,CAAS,GAAGK,CAAM,GACvDE,IAAWR,EAAQ,WACnBS,IAAWF,IAAgBC;AAEjC,MAAI,KAAK,IAAIC,CAAQ,IAAI;AACvB,WAAAT,EAAQ,YAAYO,GACb,MAAM;AAAA,IAAC;AAGhB,QAAMG,IAAW,KAAK,IAAI,KAAK,IAAI,KAAK,IAAID,CAAQ,IAAIJ,GAAYF,CAAW,GAAGC,CAAW,GACvFO,IAAY,YAAY,IAAA;AAC9B,MAAIC,IAAQ,GACRC,IAAY;AAEhB,QAAMC,IAAO,CAACC,MAAgB;AAC5B,QAAIF,EAAW;AAEf,UAAMf,IAAW,KAAK,KAAKiB,IAAMJ,KAAaD,GAAU,CAAC;AACzD,IAAAV,EAAQ,YAAYQ,IAAWC,IAAWZ,EAAaC,CAAQ,GAE3DA,IAAW,MACbc,IAAQ,sBAAsBE,CAAI;AAAA,EAEtC;AAEA,SAAAF,IAAQ,sBAAsBE,CAAI,GAE3B,MAAM;AACX,IAAAD,IAAY,IACZ,qBAAqBD,CAAK;AAAA,EAC5B;AACF,GAEaI,IAAkB,CAAChB,MAC9B,KAAK,IAAI,GAAGA,EAAQ,eAAeA,EAAQ,YAAY,GAK5CiB,IAA+B,CAC1CjB,GACAE,IAAgC,OACf;AACjB,QAAMgB,IAA8B,CAAA;AAEpC,EAAAlB,EAAQ,YAAY;AAEpB,QAAMmB,IAAQ,MAAM;AAClB,IAAAD,EAAS;AAAA,MACPnB,EAAgBC,GAASgB,EAAgBhB,CAAO,GAAG;AAAA,QACjD,aAAa;AAAA,QACb,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,GAAGE;AAAA,MAAA,CACJ;AAAA,IAAA;AAGH,UAAMkB,IAAkB,OAAO,WAAW,MAAM;AAC9C,YAAMC,IAASL,EAAgBhB,CAAO;AAEtC,MADkBqB,IAASrB,EAAQ,YACnB,KACdkB,EAAS;AAAA,QACPnB,EAAgBC,GAASqB,GAAQ;AAAA,UAC/B,aAAa;AAAA,UACb,aAAa;AAAA,UACb,YAAY;AAAA,QAAA,CACb;AAAA,MAAA;AAAA,IAGP,GAAG,GAAG;AAEN,IAAAH,EAAS,KAAK,MAAM,OAAO,aAAaE,CAAe,CAAC;AAAA,EAC1D,GAEME,IAAM,sBAAsB,MAAM;AACtC,0BAAsBH,CAAK;AAAA,EAC7B,CAAC;AAED,SAAO,MAAM;AACX,yBAAqBG,CAAG,GACxBJ,EAAS,QAAQ,CAACK,MAAYA,EAAA,CAAS;AAAA,EACzC;AACF;"}
|
|
@@ -23,7 +23,7 @@ async function B(r, e) {
|
|
|
23
23
|
const t = s.init(r);
|
|
24
24
|
return await t.preview(e), () => t.destroy();
|
|
25
25
|
}
|
|
26
|
-
async function
|
|
26
|
+
async function M(r, e) {
|
|
27
27
|
const { renderAsync: s } = await import("docx-preview"), a = new Blob([e]);
|
|
28
28
|
await s(a, r, r, {
|
|
29
29
|
inWrapper: !0,
|
|
@@ -32,11 +32,11 @@ async function C(r, e) {
|
|
|
32
32
|
breakPages: !0
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
async function
|
|
35
|
+
async function T(r, e, s) {
|
|
36
36
|
const { init: a } = await import("pptx-preview"), t = a(r, { width: s, height: Math.round(s * 0.5625), mode: "list" });
|
|
37
37
|
return await t.preview(e), () => t.destroy();
|
|
38
38
|
}
|
|
39
|
-
function
|
|
39
|
+
function W(r, e) {
|
|
40
40
|
const s = new TextDecoder("utf-8"), a = document.createElement("pre");
|
|
41
41
|
a.className = o["file-preview-text"], a.textContent = s.decode(e), r.appendChild(a);
|
|
42
42
|
}
|
|
@@ -60,11 +60,11 @@ const D = ({
|
|
|
60
60
|
if (i === "excel")
|
|
61
61
|
t.current = await B(f, c);
|
|
62
62
|
else if (i === "word")
|
|
63
|
-
await
|
|
63
|
+
await M(f, c);
|
|
64
64
|
else if (i === "ppt") {
|
|
65
65
|
const y = f.clientWidth || 852;
|
|
66
|
-
t.current = await
|
|
67
|
-
} else i === "text" &&
|
|
66
|
+
t.current = await T(f, c, y);
|
|
67
|
+
} else i === "text" && W(f, c);
|
|
68
68
|
} catch (c) {
|
|
69
69
|
l || w(c instanceof Error ? c.message : "预览加载失败");
|
|
70
70
|
} finally {
|
|
@@ -75,14 +75,13 @@ const D = ({
|
|
|
75
75
|
var c;
|
|
76
76
|
l = !0, (c = t.current) == null || c.call(t), t.current = void 0, f.innerHTML = "";
|
|
77
77
|
};
|
|
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(
|
|
79
|
-
"
|
|
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("iframe", { src: e, title: r.name, className: o["file-preview-iframe"] }) : 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(
|
|
79
|
+
"div",
|
|
80
80
|
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
className: o["file-preview-iframe"]
|
|
81
|
+
className: b(o["file-preview-office"], o["file-preview-office-wrap"]),
|
|
82
|
+
children: /* @__PURE__ */ n(x, { spinning: d, classNames: { root: o["file-preview-office-spin"] }, children: p ? /* @__PURE__ */ n(u, { description: p }) : /* @__PURE__ */ n("div", { ref: a, className: o["file-preview-office-inner"] }) })
|
|
84
83
|
}
|
|
85
|
-
) :
|
|
84
|
+
) : /* @__PURE__ */ n(u, { description: s }) : /* @__PURE__ */ n(u, { description: "无可预览地址" });
|
|
86
85
|
};
|
|
87
86
|
export {
|
|
88
87
|
D as default
|
|
@@ -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 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
|
|
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 <iframe src={previewUrl} title={file.name} className={styles['file-preview-iframe']} />;\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\n className={classNames(styles['file-preview-office'], styles['file-preview-office-wrap'])}\n >\n <Spin spinning={loading} classNames={{ root: styles['file-preview-office-spin'] }}>\n {error ? (\n <Empty description={error} />\n ) : (\n <div ref={containerRef} className={styles['file-preview-office-inner']} />\n )}\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":"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"}
|
|
@@ -6,10 +6,12 @@ interface FilterSelectProps extends BaseFilterProps {
|
|
|
6
6
|
options: FilterOption[];
|
|
7
7
|
value?: FilterSelectValue;
|
|
8
8
|
onChange?: (value: FilterSelectValue) => void;
|
|
9
|
-
/**
|
|
9
|
+
/** 默认值:与默认值相同时视为未筛选(除非 showDefaultAsSelected) */
|
|
10
10
|
defaultValue?: string | number;
|
|
11
|
-
/**
|
|
11
|
+
/** 多选默认值:与默认集合相同时视为未筛选(除非 showDefaultAsSelected) */
|
|
12
12
|
defaultValues?: (string | number)[];
|
|
13
|
+
/** 为 true 时,value 等于默认仍展示在「您已选择」并保持选中态 */
|
|
14
|
+
showDefaultAsSelected?: boolean;
|
|
13
15
|
placeholder?: string;
|
|
14
16
|
searchable?: boolean;
|
|
15
17
|
/** 是否多选 */
|