feat: artifacts style

This commit is contained in:
Dogtiti 2024-07-25 23:29:29 +08:00
parent 51e8f0440d
commit c27ef6ffbf
4 changed files with 52 additions and 30 deletions

View File

@ -1,8 +1,26 @@
.artifact {
display: block;
display: flex;
width: 100%;
height: 100%;
position: relative;
flex-direction: column;
&-header {
display: flex;
align-items: center;
height: 36px;
padding: 20px;
background: var(--second);
}
&-title {
flex: 1;
text-align: center;
font-weight: bold;
font-size: 24px;
}
&-content {
flex-grow: 1;
padding: 0 20px 20px 20px;
background-color: var(--second);
}
}
.artifact-iframe {

View File

@ -18,7 +18,7 @@ import styles from "./artifact.module.scss";
export function HTMLPreview(props: {
code: string;
autoHeight?: boolean;
height?: number;
height?: number | string;
onLoad?: (title?: string) => void;
}) {
const ref = useRef<HTMLIFrameElement>(null);
@ -185,7 +185,6 @@ export function Artifact() {
const [code, setCode] = useState("");
const [loading, setLoading] = useState(true);
const [fileName, setFileName] = useState("");
const { height } = useWindowSize();
useEffect(() => {
if (id) {
@ -205,33 +204,28 @@ export function Artifact() {
}, [id]);
return (
<div className={styles.artifact}>
<div
style={{
height: 36,
display: "flex",
alignItems: "center",
padding: 12,
}}
>
<div className={styles["artifact"]}>
<div className={styles["artifact-header"]}>
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
<IconButton bordered icon={<GithubIcon />} shadow />
</a>
<div style={{ flex: 1, textAlign: "center" }}>NextChat Artifact</div>
<div className={styles["artifact-title"]}>NextChat Artifact</div>
<ArtifactShareButton id={id} getCode={() => code} fileName={fileName} />
</div>
{loading && <Loading />}
{code && (
<HTMLPreview
code={code}
autoHeight={false}
height={height - 36}
onLoad={(title) => {
setFileName(title as string);
setLoading(false);
}}
/>
)}
<div className={styles["artifact-content"]}>
{loading && <Loading />}
{code && (
<HTMLPreview
code={code}
autoHeight={false}
height={"100%"}
onLoad={(title) => {
setFileName(title as string);
setLoading(false);
}}
/>
)}
</div>
</div>
);
}

View File

@ -641,12 +641,13 @@ export function ChatActions(props: {
]}
onClose={() => setShowPluginSelector(false)}
onSelection={(s) => {
if (s.length === 0) return;
const plugin = s[0];
chatStore.updateCurrentSession((session) => {
session.mask.plugin = s;
});
showToast(plugin);
if (plugin) {
showToast(plugin);
}
}}
/>
)}

View File

@ -14,7 +14,8 @@ import React from "react";
import { useDebouncedCallback } from "use-debounce";
import { showImageModal, FullScreen } from "./ui-lib";
import { ArtifactShareButton, HTMLPreview } from "./artifact";
import { Plugin } from "../constant";
import { useChatStore } from "../store";
export function Mermaid(props: { code: string }) {
const ref = useRef<HTMLDivElement>(null);
const [hasError, setHasError] = useState(false);
@ -67,6 +68,9 @@ export function PreCode(props: { children: any }) {
const [mermaidCode, setMermaidCode] = useState("");
const [htmlCode, setHtmlCode] = useState("");
const { height } = useWindowSize();
const chatStore = useChatStore();
const session = chatStore.currentSession();
const plugins = session.mask?.plugin;
const renderArtifacts = useDebouncedCallback(() => {
if (!ref.current) return;
@ -87,6 +91,11 @@ export function PreCode(props: { children: any }) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [refText]);
const enableArtifacts = useMemo(
() => plugins?.includes(Plugin.Artifact),
[plugins],
);
return (
<>
<pre ref={ref}>
@ -104,7 +113,7 @@ export function PreCode(props: { children: any }) {
{mermaidCode.length > 0 && (
<Mermaid code={mermaidCode} key={mermaidCode} />
)}
{htmlCode.length > 0 && (
{htmlCode.length > 0 && enableArtifacts && (
<FullScreen className="no-dark html" right={70}>
<ArtifactShareButton
style={{ position: "absolute", right: 20, top: 10 }}