@infinilabs/doc-detail 0.0.0 → 0.0.2
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/doc-detail.cjs +171 -12
- package/dist/doc-detail.js +83964 -16429
- package/dist/index.d.ts +47 -52
- package/package.json +9 -1
- package/src/App.tsx +15 -44
- package/src/components/ActionButton/index.tsx +51 -0
- package/src/components/DocDetail/components/AIInterpretation/index.tsx +6 -81
- package/src/components/DocDetail/components/Preview/components/Docx/index.tsx +37 -0
- package/src/components/DocDetail/components/Preview/components/Markdown/index.tsx +30 -0
- package/src/components/DocDetail/components/Preview/components/Pdf/index.tsx +20 -31
- package/src/components/DocDetail/components/Preview/components/Pptx/index.tsx +37 -0
- package/src/components/DocDetail/components/Preview/index.tsx +39 -5
- package/src/components/DocDetail/index.tsx +137 -114
- package/src/components/index.tsx +2 -1
- package/src/components/DocDetail/components/Preview/components/Pdf/test.pdf +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,63 +1,55 @@
|
|
|
1
|
+
import { ButtonProps } from 'antd';
|
|
1
2
|
import { FC } from 'react';
|
|
3
|
+
import { HTMLAttributes } from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
export declare const ActionButton: FC<ActionButtonProps>;
|
|
7
|
+
|
|
8
|
+
declare type ActionButtonProps = ButtonProps;
|
|
2
9
|
|
|
3
10
|
export declare const DocDetail: FC<DocDetailProps>;
|
|
4
11
|
|
|
5
|
-
declare interface DocDetailProps {
|
|
12
|
+
declare interface DocDetailProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
13
|
data: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
id?: string;
|
|
15
|
+
created?: ReactNode;
|
|
16
|
+
updated?: ReactNode;
|
|
17
|
+
_system?: {
|
|
18
|
+
owner_id?: string;
|
|
19
|
+
parent_path?: string;
|
|
20
|
+
tenant_id?: string;
|
|
11
21
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
icon: string;
|
|
21
|
-
thumbnail: string;
|
|
22
|
-
tags: string[];
|
|
23
|
-
url: string;
|
|
24
|
-
size: number;
|
|
25
|
-
owner: {
|
|
26
|
-
avatar: string;
|
|
27
|
-
username: string;
|
|
28
|
-
userid: string;
|
|
22
|
+
metadata?: {
|
|
23
|
+
ai_insights?: string;
|
|
24
|
+
colors?: string[];
|
|
25
|
+
content_type?: MetadataContentType;
|
|
26
|
+
height?: number;
|
|
27
|
+
mime_type?: string;
|
|
28
|
+
users?: null | unknown;
|
|
29
|
+
width?: number;
|
|
29
30
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
file_extension: string;
|
|
35
|
-
icon_link: string;
|
|
36
|
-
has_thumbnail: boolean;
|
|
37
|
-
kind: string;
|
|
38
|
-
parents: string[];
|
|
39
|
-
properties: Record<string, string>;
|
|
40
|
-
spaces: string[];
|
|
41
|
-
starred: boolean;
|
|
42
|
-
driveId: string;
|
|
43
|
-
thumbnail_link: string;
|
|
44
|
-
video_media_metadata?: {
|
|
45
|
-
durationMillis: string;
|
|
46
|
-
width: number;
|
|
47
|
-
height: number;
|
|
48
|
-
};
|
|
49
|
-
image_media_metadata?: {
|
|
50
|
-
width: number;
|
|
51
|
-
height: number;
|
|
52
|
-
};
|
|
31
|
+
source?: {
|
|
32
|
+
type?: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
id?: string;
|
|
53
35
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
36
|
+
type?: string;
|
|
37
|
+
category?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
summary?: string;
|
|
40
|
+
icon?: string;
|
|
41
|
+
thumbnail?: string;
|
|
42
|
+
cover?: string;
|
|
43
|
+
tags?: string[];
|
|
44
|
+
url?: string;
|
|
45
|
+
size?: ReactNode;
|
|
46
|
+
owner: {
|
|
47
|
+
type?: string;
|
|
48
|
+
id?: string;
|
|
49
|
+
icon?: string;
|
|
50
|
+
title?: string;
|
|
51
|
+
subtitle?: string;
|
|
52
|
+
cover?: string;
|
|
61
53
|
};
|
|
62
54
|
};
|
|
63
55
|
i18n?: {
|
|
@@ -74,6 +66,9 @@ declare interface DocDetailProps {
|
|
|
74
66
|
size?: string;
|
|
75
67
|
};
|
|
76
68
|
};
|
|
69
|
+
extraButtons?: ReactNode[];
|
|
77
70
|
}
|
|
78
71
|
|
|
72
|
+
declare type MetadataContentType = "image" | "video" | "markdown" | "pdf" | "docx" | "pptx" | "xlsx";
|
|
73
|
+
|
|
79
74
|
export { }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infinilabs/doc-detail",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/doc-detail.cjs",
|
|
7
7
|
"module": "dist/doc-detail.js",
|
|
@@ -22,9 +22,13 @@
|
|
|
22
22
|
"preview": "vite preview"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"@ant-design/x-markdown": "^2.1.3",
|
|
25
26
|
"antd": "^6.0.0",
|
|
26
27
|
"clsx": "^2.1.1",
|
|
28
|
+
"docx-preview": "^0.3.7",
|
|
27
29
|
"lucide-react": "^0.562.0",
|
|
30
|
+
"motion": "^12.23.26",
|
|
31
|
+
"pptx-preview": "^1.0.7",
|
|
28
32
|
"react": "^19.2.0",
|
|
29
33
|
"react-dom": "^19.2.0",
|
|
30
34
|
"react-pdf": "^10.2.0",
|
|
@@ -46,5 +50,9 @@
|
|
|
46
50
|
"antd": ">=5",
|
|
47
51
|
"react": ">=17",
|
|
48
52
|
"react-dom": ">=17"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/infinilabs/ci"
|
|
49
57
|
}
|
|
50
58
|
}
|
package/src/App.tsx
CHANGED
|
@@ -1,64 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bot } from "lucide-react";
|
|
2
|
+
import { ActionButton, DocDetail } from "./components";
|
|
2
3
|
|
|
3
4
|
const App = () => {
|
|
4
5
|
return (
|
|
5
6
|
<div className="h-screen">
|
|
6
7
|
<DocDetail
|
|
7
8
|
data={{
|
|
9
|
+
type: "file",
|
|
8
10
|
source: {
|
|
9
|
-
type: "connector",
|
|
10
11
|
name: "My Hugo Site",
|
|
11
|
-
id: "e806831dacc3",
|
|
12
12
|
},
|
|
13
13
|
category: "report",
|
|
14
|
-
categories: ["business", "quarterly_reports"],
|
|
15
|
-
cover: "https://picsum.photos/seed/report-cover/640/360",
|
|
16
14
|
title: "Q3 Business Report",
|
|
17
|
-
summary: "An overview of the company financial performance for Q3.",
|
|
18
|
-
type: "PDF",
|
|
19
|
-
lang: "en",
|
|
20
|
-
content:
|
|
21
|
-
"This quarters revenue increased by 15%, driven by strong sales in the APAC region...",
|
|
22
15
|
icon: "https://picsum.photos/seed/file-icon/40/40",
|
|
23
|
-
thumbnail: "https://picsum.photos/seed/report-thumb/320/180",
|
|
24
|
-
tags: ["finance", "quarterly", "business", "report"],
|
|
25
|
-
url: "https://drive.google.com/file/d/abc123/view",
|
|
26
16
|
size: 1048576,
|
|
27
|
-
|
|
28
|
-
avatar: "https://picsum.photos/seed/user-avatar/64/64",
|
|
29
|
-
username: "jdoe",
|
|
30
|
-
userid: "user123",
|
|
31
|
-
},
|
|
17
|
+
url: "http://192.168.3.181:9101/coco-server/test.pdf",
|
|
32
18
|
metadata: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
last_reviewed: "2024-10-20",
|
|
36
|
-
file_extension: "pdf",
|
|
37
|
-
icon_link: "https://picsum.photos/seed/filetype-icon/40/40",
|
|
38
|
-
has_thumbnail: true,
|
|
39
|
-
kind: "drive#file",
|
|
40
|
-
parents: ["folder123"],
|
|
41
|
-
properties: { shared: "true" },
|
|
42
|
-
spaces: ["drive"],
|
|
43
|
-
starred: false,
|
|
44
|
-
driveId: "drive123",
|
|
45
|
-
thumbnail_link: "https://picsum.photos/seed/file-thumb/320/180",
|
|
46
|
-
video_media_metadata: {
|
|
47
|
-
durationMillis: "60000",
|
|
48
|
-
width: 1920,
|
|
49
|
-
height: 1080,
|
|
50
|
-
},
|
|
51
|
-
image_media_metadata: { width: 1024, height: 768 },
|
|
19
|
+
content_type: "pdf",
|
|
20
|
+
ai_insights: `# AI Interpretation\n### Welcome to XMarkdown!\n- Project 1 \n- Project 2\n- Project 3`,
|
|
52
21
|
},
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
avatar: "https://picsum.photos/seed/editor-avatar/64/64",
|
|
56
|
-
username: "editor123",
|
|
57
|
-
userid: "editor123@example.com",
|
|
58
|
-
},
|
|
59
|
-
timestamp: "2024-11-01T15:30:00Z",
|
|
22
|
+
owner: {
|
|
23
|
+
title: "Alice Johnson",
|
|
60
24
|
},
|
|
25
|
+
created: "2026-01-09T02:30:10.188Z",
|
|
26
|
+
updated: "2026-01-09T02:30:10.188Z",
|
|
61
27
|
}}
|
|
28
|
+
extraButtons={[
|
|
29
|
+
<ActionButton key="bot" icon={<Bot />}>
|
|
30
|
+
Continue Chat
|
|
31
|
+
</ActionButton>,
|
|
32
|
+
]}
|
|
62
33
|
/>
|
|
63
34
|
</div>
|
|
64
35
|
);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Button, type ButtonProps } from "antd";
|
|
2
|
+
import { useState, type FC, type MouseEvent } from "react";
|
|
3
|
+
import { motion } from "motion/react";
|
|
4
|
+
|
|
5
|
+
export type ActionButtonProps = ButtonProps;
|
|
6
|
+
|
|
7
|
+
const ActionButton: FC<ActionButtonProps> = (props) => {
|
|
8
|
+
const { icon, children, onMouseOver, onMouseOut, ...rest } = props;
|
|
9
|
+
|
|
10
|
+
const [hovered, setHovered] = useState(false);
|
|
11
|
+
|
|
12
|
+
const handleMouseOver = (event: MouseEvent<HTMLButtonElement>) => {
|
|
13
|
+
setHovered(true);
|
|
14
|
+
|
|
15
|
+
onMouseOver?.(event);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handleMouseOut = (event: MouseEvent<HTMLButtonElement>) => {
|
|
19
|
+
setHovered(false);
|
|
20
|
+
|
|
21
|
+
onMouseOut?.(event);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Button
|
|
26
|
+
{...rest}
|
|
27
|
+
color="primary"
|
|
28
|
+
variant="filled"
|
|
29
|
+
shape="round"
|
|
30
|
+
className="gap-0"
|
|
31
|
+
onMouseOver={handleMouseOver}
|
|
32
|
+
onMouseOut={handleMouseOut}
|
|
33
|
+
>
|
|
34
|
+
<span className="inline-flex items-center children:size-4">{icon}</span>
|
|
35
|
+
|
|
36
|
+
<motion.span
|
|
37
|
+
className="overflow-hidden"
|
|
38
|
+
initial={false}
|
|
39
|
+
animate={{
|
|
40
|
+
width: hovered ? "auto" : 0,
|
|
41
|
+
opacity: Number(hovered),
|
|
42
|
+
paddingLeft: Number(hovered) * 8,
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
{children}
|
|
46
|
+
</motion.span>
|
|
47
|
+
</Button>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default ActionButton;
|
|
@@ -1,99 +1,24 @@
|
|
|
1
1
|
import type { FC } from "react";
|
|
2
|
-
import type { DocDetailProps } from "../..";
|
|
3
2
|
import { Collapse } from "antd";
|
|
4
3
|
|
|
4
|
+
import type { DocDetailProps } from "@/components/DocDetail";
|
|
5
|
+
import Markdown from "../Preview/components/Markdown";
|
|
6
|
+
|
|
5
7
|
const AIInterpretation: FC<DocDetailProps> = (props) => {
|
|
6
|
-
const { i18n } = props;
|
|
8
|
+
const { data, i18n } = props;
|
|
7
9
|
|
|
8
10
|
return (
|
|
9
11
|
<Collapse
|
|
10
12
|
size="small"
|
|
11
13
|
classNames={{
|
|
12
14
|
root: "bg-transparent",
|
|
15
|
+
body: "p-4!",
|
|
13
16
|
}}
|
|
14
17
|
items={[
|
|
15
18
|
{
|
|
16
19
|
key: "ai-interpretation",
|
|
17
20
|
label: i18n?.labels?.aiInterpretation ?? "AI Interpretation",
|
|
18
|
-
children:
|
|
19
|
-
<p>
|
|
20
|
-
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ad
|
|
21
|
-
doloribus unde porro, est molestiae voluptates provident quam ex
|
|
22
|
-
cumque quasi asperiores dicta vero. Ullam corrupti exercitationem
|
|
23
|
-
rerum temporibus tempora fugit. Nihil impedit odit vel
|
|
24
|
-
reprehenderit itaque voluptatum laborum dolore quae earum
|
|
25
|
-
explicabo quibusdam laudantium officia, esse, recusandae ratione?
|
|
26
|
-
Vero temporibus rem, quisquam facilis vel officia possimus nihil
|
|
27
|
-
porro ad minus! Similique explicabo fugit consectetur modi nulla
|
|
28
|
-
quasi unde vitae non eos, vel dolorem dolor voluptates veniam.
|
|
29
|
-
Consectetur minima voluptatem quisquam ipsa facere! Maxime nam
|
|
30
|
-
quae blanditiis architecto ipsa tempore qui. Pariatur earum
|
|
31
|
-
debitis quis magnam temporibus impedit tempore reiciendis,
|
|
32
|
-
exercitationem veritatis corrupti tempora et suscipit totam unde
|
|
33
|
-
nulla quae perspiciatis molestiae harum dolores iusto corporis!
|
|
34
|
-
Architecto explicabo facilis consequuntur neque. Fuga quisquam
|
|
35
|
-
placeat fugit rerum nam laborum ad, debitis nemo magnam eius
|
|
36
|
-
officia tenetur, ducimus incidunt velit assumenda nisi,
|
|
37
|
-
praesentium perferendis quibusdam commodi! Ab tenetur minima ad
|
|
38
|
-
quae aspernatur maiores! Nostrum rem voluptatibus ullam
|
|
39
|
-
reiciendis, harum quod quas nesciunt id voluptatum natus quisquam?
|
|
40
|
-
Quam rerum deleniti error labore impedit, molestiae sapiente
|
|
41
|
-
maxime velit dolore. Cumque unde repellat eligendi nemo
|
|
42
|
-
consectetur! Error porro non in! Inventore, numquam, quod quam
|
|
43
|
-
tempore officiis placeat optio non ullam tenetur voluptates
|
|
44
|
-
laborum ipsam dolores a eos vitae nemo saepe architecto culpa,
|
|
45
|
-
soluta velit! Id, magni. Laborum consequuntur magni architecto
|
|
46
|
-
velit, accusantium delectus alias, amet libero, voluptatibus iure
|
|
47
|
-
fugit magnam corporis id quas ut suscipit necessitatibus ad nihil.
|
|
48
|
-
Molestias nesciunt, dolore facere autem ratione voluptatum vero.
|
|
49
|
-
Saepe, nihil asperiores necessitatibus delectus fugiat dolorem
|
|
50
|
-
cum, temporibus fuga dolores ipsum officiis odio repellendus
|
|
51
|
-
repudiandae similique incidunt quisquam. Beatae, illo! Iste
|
|
52
|
-
mollitia dolor fuga repellendus, perferendis accusamus modi
|
|
53
|
-
beatae! Ducimus repellat voluptate asperiores, accusantium omnis
|
|
54
|
-
voluptatem beatae laudantium provident? Et sequi vel molestiae
|
|
55
|
-
temporibus repellat nulla dolorem adipisci quod dignissimos
|
|
56
|
-
aliquid! Assumenda, minima laboriosam. Voluptates amet nobis odit
|
|
57
|
-
veritatis!Lorem ipsum dolor, sit amet consectetur adipisicing
|
|
58
|
-
elit. Ad doloribus unde porro, est molestiae voluptates provident
|
|
59
|
-
quam ex cumque quasi asperiores dicta vero. Ullam corrupti
|
|
60
|
-
exercitationem rerum temporibus tempora fugit. Nihil impedit odit
|
|
61
|
-
vel reprehenderit itaque voluptatum laborum dolore quae earum
|
|
62
|
-
explicabo quibusdam laudantium officia, esse, recusandae ratione?
|
|
63
|
-
Vero temporibus rem, quisquam facilis vel officia possimus nihil
|
|
64
|
-
porro ad minus! Similique explicabo fugit consectetur modi nulla
|
|
65
|
-
quasi unde vitae non eos, vel dolorem dolor voluptates veniam.
|
|
66
|
-
Consectetur minima voluptatem quisquam ipsa facere! Maxime nam
|
|
67
|
-
quae blanditiis architecto ipsa tempore qui. Pariatur earum
|
|
68
|
-
debitis quis magnam temporibus impedit tempore reiciendis,
|
|
69
|
-
exercitationem veritatis corrupti tempora et suscipit totam unde
|
|
70
|
-
nulla quae perspiciatis molestiae harum dolores iusto corporis!
|
|
71
|
-
Architecto explicabo facilis consequuntur neque. Fuga quisquam
|
|
72
|
-
placeat fugit rerum nam laborum ad, debitis nemo magnam eius
|
|
73
|
-
officia tenetur, ducimus incidunt velit assumenda nisi,
|
|
74
|
-
praesentium perferendis quibusdam commodi! Ab tenetur minima ad
|
|
75
|
-
quae aspernatur maiores! Nostrum rem voluptatibus ullam
|
|
76
|
-
reiciendis, harum quod quas nesciunt id voluptatum natus quisquam?
|
|
77
|
-
Quam rerum deleniti error labore impedit, molestiae sapiente
|
|
78
|
-
maxime velit dolore. Cumque unde repellat eligendi nemo
|
|
79
|
-
consectetur! Error porro non in! Inventore, numquam, quod quam
|
|
80
|
-
tempore officiis placeat optio non ullam tenetur voluptates
|
|
81
|
-
laborum ipsam dolores a eos vitae nemo saepe architecto culpa,
|
|
82
|
-
soluta velit! Id, magni. Laborum consequuntur magni architecto
|
|
83
|
-
velit, accusantium delectus alias, amet libero, voluptatibus iure
|
|
84
|
-
fugit magnam corporis id quas ut suscipit necessitatibus ad nihil.
|
|
85
|
-
Molestias nesciunt, dolore facere autem ratione voluptatum vero.
|
|
86
|
-
Saepe, nihil asperiores necessitatibus delectus fugiat dolorem
|
|
87
|
-
cum, temporibus fuga dolores ipsum officiis odio repellendus
|
|
88
|
-
repudiandae similique incidunt quisquam. Beatae, illo! Iste
|
|
89
|
-
mollitia dolor fuga repellendus, perferendis accusamus modi
|
|
90
|
-
beatae! Ducimus repellat voluptate asperiores, accusantium omnis
|
|
91
|
-
voluptatem beatae laudantium provident? Et sequi vel molestiae
|
|
92
|
-
temporibus repellat nulla dolorem adipisci quod dignissimos
|
|
93
|
-
aliquid! Assumenda, minima laboriosam. Voluptates amet nobis odit
|
|
94
|
-
veritatis!
|
|
95
|
-
</p>
|
|
96
|
-
),
|
|
21
|
+
children: <Markdown content={data?.metadata?.ai_insights} />,
|
|
97
22
|
},
|
|
98
23
|
]}
|
|
99
24
|
/>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DocDetailProps } from "@/components/DocDetail";
|
|
2
|
+
import { useEffect, useRef, type FC } from "react";
|
|
3
|
+
import { renderAsync } from "docx-preview";
|
|
4
|
+
|
|
5
|
+
interface DocxProps extends DocDetailProps {
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const Docx: FC<DocxProps> = (props) => {
|
|
10
|
+
const { url } = props;
|
|
11
|
+
|
|
12
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
13
|
+
|
|
14
|
+
const renderDocx = async () => {
|
|
15
|
+
if (!containerRef.current) return;
|
|
16
|
+
|
|
17
|
+
const response = await fetch(url);
|
|
18
|
+
|
|
19
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
20
|
+
|
|
21
|
+
containerRef.current.innerHTML = "";
|
|
22
|
+
|
|
23
|
+
renderAsync(arrayBuffer, containerRef.current!, void 0, {
|
|
24
|
+
inWrapper: false,
|
|
25
|
+
ignoreWidth: true,
|
|
26
|
+
ignoreHeight: true,
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
renderDocx();
|
|
32
|
+
}, [url]);
|
|
33
|
+
|
|
34
|
+
return <div ref={containerRef} className="[&>.docx]:p-0!" />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default Docx;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { XMarkdown, type XMarkdownProps } from "@ant-design/x-markdown";
|
|
2
|
+
import { useEffect, useState, type FC } from "react";
|
|
3
|
+
|
|
4
|
+
interface MarkdownProps extends XMarkdownProps {
|
|
5
|
+
url?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Markdown: FC<MarkdownProps> = (props) => {
|
|
9
|
+
const { url, ...rest } = props;
|
|
10
|
+
|
|
11
|
+
const [content, setContent] = useState(rest.content);
|
|
12
|
+
|
|
13
|
+
const fetchContent = async (url: string) => {
|
|
14
|
+
const response = await fetch(url);
|
|
15
|
+
|
|
16
|
+
const text = await response.text();
|
|
17
|
+
|
|
18
|
+
setContent(text);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!url) return;
|
|
23
|
+
|
|
24
|
+
fetchContent(url);
|
|
25
|
+
}, [url]);
|
|
26
|
+
|
|
27
|
+
return <XMarkdown {...rest} content={content} />;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default Markdown;
|
|
@@ -1,46 +1,35 @@
|
|
|
1
1
|
import { Document, Page, pdfjs } from "react-pdf";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useState, type FC } from "react";
|
|
3
|
+
import type { DocDetailProps } from "@/components/DocDetail";
|
|
4
|
+
import { Pagination } from "antd";
|
|
5
5
|
|
|
6
6
|
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
interface PdfProps extends DocDetailProps {
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Pdf: FC<PdfProps> = (props) => {
|
|
13
|
+
const { url } = props;
|
|
14
|
+
|
|
9
15
|
const [numPages, setNumPages] = useState(0);
|
|
10
16
|
const [pageNumber, setPageNumber] = useState(1);
|
|
11
17
|
|
|
12
18
|
return (
|
|
13
19
|
<div className="flex flex-col gap-2">
|
|
14
|
-
<div className="
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
key={page}
|
|
24
|
-
className={cn(
|
|
25
|
-
"inline-flex items-center h-6 px-3 rounded-lg cursor-pointer bg-bg-layout text-text-secondary",
|
|
26
|
-
{
|
|
27
|
-
"text-primary bg-primary-bg": pageNumber === page,
|
|
28
|
-
}
|
|
29
|
-
)}
|
|
30
|
-
onClick={() => {
|
|
31
|
-
setPageNumber(page);
|
|
32
|
-
}}
|
|
33
|
-
>
|
|
34
|
-
第{page}页
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
})}
|
|
38
|
-
</div>
|
|
39
|
-
)}
|
|
20
|
+
<div className="flex justify-end">
|
|
21
|
+
<Pagination
|
|
22
|
+
size="small"
|
|
23
|
+
pageSize={1}
|
|
24
|
+
total={numPages}
|
|
25
|
+
current={pageNumber}
|
|
26
|
+
onChange={(page) => setPageNumber(page)}
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
40
29
|
|
|
41
30
|
<div className="border border-solid border-border rounded-lg overflow-hidden">
|
|
42
31
|
<Document
|
|
43
|
-
file={
|
|
32
|
+
file={url}
|
|
44
33
|
onLoadSuccess={(pdf) => {
|
|
45
34
|
setNumPages(pdf.numPages);
|
|
46
35
|
}}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect, useRef, type FC } from "react";
|
|
2
|
+
import { init } from "pptx-preview";
|
|
3
|
+
|
|
4
|
+
import type { DocDetailProps } from "@/components/DocDetail";
|
|
5
|
+
|
|
6
|
+
interface PptxProps extends DocDetailProps {
|
|
7
|
+
url: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Pptx: FC<PptxProps> = (props) => {
|
|
11
|
+
const { url } = props;
|
|
12
|
+
|
|
13
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
14
|
+
|
|
15
|
+
const renderPdf = async () => {
|
|
16
|
+
if (!containerRef.current) return;
|
|
17
|
+
|
|
18
|
+
const pptx = init(containerRef.current, {
|
|
19
|
+
width: 960,
|
|
20
|
+
height: 540,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const response = await fetch(url);
|
|
24
|
+
|
|
25
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
26
|
+
|
|
27
|
+
pptx.preview(arrayBuffer);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
renderPdf();
|
|
32
|
+
}, [url]);
|
|
33
|
+
|
|
34
|
+
return <div ref={containerRef} />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default Pptx;
|
|
@@ -1,16 +1,49 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
1
|
+
import { type FC } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
DocDetailProps,
|
|
4
|
+
MetadataContentType,
|
|
5
|
+
} from "@/components/DocDetail";
|
|
3
6
|
import { Collapse } from "antd";
|
|
4
7
|
import Pdf from "./components/Pdf";
|
|
8
|
+
import Markdown from "./components/Markdown";
|
|
9
|
+
import Docx from "./components/Docx";
|
|
10
|
+
import Pptx from "./components/Pptx";
|
|
5
11
|
|
|
6
12
|
const Preview: FC<DocDetailProps> = (props) => {
|
|
7
13
|
const { data, i18n } = props;
|
|
8
14
|
|
|
15
|
+
const renderFile = (type: MetadataContentType, url: string) => {
|
|
16
|
+
if (type === "markdown") {
|
|
17
|
+
return <Markdown url={url} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (type === "pdf") {
|
|
21
|
+
return <Pdf url={url} {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (type === "docx") {
|
|
25
|
+
return <Docx url={url} {...props} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (type === "pptx") {
|
|
29
|
+
return <Pptx url={url} {...props} />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
|
|
9
35
|
const renderContent = () => {
|
|
10
|
-
const {
|
|
36
|
+
const { url } = data;
|
|
37
|
+
const type = data?.metadata?.content_type;
|
|
38
|
+
|
|
39
|
+
if (!type || !url) return;
|
|
11
40
|
|
|
12
41
|
if (type === "image") {
|
|
13
|
-
return <img src={
|
|
42
|
+
return <img src={url} className="w-full" />;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (type === "video") {
|
|
46
|
+
return <video src={url} className="w-full" controls />;
|
|
14
47
|
}
|
|
15
48
|
|
|
16
49
|
return (
|
|
@@ -19,12 +52,13 @@ const Preview: FC<DocDetailProps> = (props) => {
|
|
|
19
52
|
defaultActiveKey={["preview"]}
|
|
20
53
|
classNames={{
|
|
21
54
|
root: "bg-transparent",
|
|
55
|
+
body: "p-4!",
|
|
22
56
|
}}
|
|
23
57
|
items={[
|
|
24
58
|
{
|
|
25
59
|
key: "preview",
|
|
26
60
|
label: i18n?.labels?.preview ?? "Preview",
|
|
27
|
-
children:
|
|
61
|
+
children: renderFile(type, url),
|
|
28
62
|
},
|
|
29
63
|
]}
|
|
30
64
|
/>
|