mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	feat: artifacts style
This commit is contained in:
		@@ -1,8 +1,26 @@
 | 
				
			|||||||
.artifact {
 | 
					.artifact {
 | 
				
			||||||
  display: block;
 | 
					  display: flex;
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 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 {
 | 
					.artifact-iframe {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ import styles from "./artifact.module.scss";
 | 
				
			|||||||
export function HTMLPreview(props: {
 | 
					export function HTMLPreview(props: {
 | 
				
			||||||
  code: string;
 | 
					  code: string;
 | 
				
			||||||
  autoHeight?: boolean;
 | 
					  autoHeight?: boolean;
 | 
				
			||||||
  height?: number;
 | 
					  height?: number | string;
 | 
				
			||||||
  onLoad?: (title?: string) => void;
 | 
					  onLoad?: (title?: string) => void;
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  const ref = useRef<HTMLIFrameElement>(null);
 | 
					  const ref = useRef<HTMLIFrameElement>(null);
 | 
				
			||||||
@@ -185,7 +185,6 @@ export function Artifact() {
 | 
				
			|||||||
  const [code, setCode] = useState("");
 | 
					  const [code, setCode] = useState("");
 | 
				
			||||||
  const [loading, setLoading] = useState(true);
 | 
					  const [loading, setLoading] = useState(true);
 | 
				
			||||||
  const [fileName, setFileName] = useState("");
 | 
					  const [fileName, setFileName] = useState("");
 | 
				
			||||||
  const { height } = useWindowSize();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    if (id) {
 | 
					    if (id) {
 | 
				
			||||||
@@ -205,33 +204,28 @@ export function Artifact() {
 | 
				
			|||||||
  }, [id]);
 | 
					  }, [id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={styles.artifact}>
 | 
					    <div className={styles["artifact"]}>
 | 
				
			||||||
      <div
 | 
					      <div className={styles["artifact-header"]}>
 | 
				
			||||||
        style={{
 | 
					 | 
				
			||||||
          height: 36,
 | 
					 | 
				
			||||||
          display: "flex",
 | 
					 | 
				
			||||||
          alignItems: "center",
 | 
					 | 
				
			||||||
          padding: 12,
 | 
					 | 
				
			||||||
        }}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <a href={REPO_URL} target="_blank" rel="noopener noreferrer">
 | 
					        <a href={REPO_URL} target="_blank" rel="noopener noreferrer">
 | 
				
			||||||
          <IconButton bordered icon={<GithubIcon />} shadow />
 | 
					          <IconButton bordered icon={<GithubIcon />} shadow />
 | 
				
			||||||
        </a>
 | 
					        </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} />
 | 
					        <ArtifactShareButton id={id} getCode={() => code} fileName={fileName} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      {loading && <Loading />}
 | 
					      <div className={styles["artifact-content"]}>
 | 
				
			||||||
      {code && (
 | 
					        {loading && <Loading />}
 | 
				
			||||||
        <HTMLPreview
 | 
					        {code && (
 | 
				
			||||||
          code={code}
 | 
					          <HTMLPreview
 | 
				
			||||||
          autoHeight={false}
 | 
					            code={code}
 | 
				
			||||||
          height={height - 36}
 | 
					            autoHeight={false}
 | 
				
			||||||
          onLoad={(title) => {
 | 
					            height={"100%"}
 | 
				
			||||||
            setFileName(title as string);
 | 
					            onLoad={(title) => {
 | 
				
			||||||
            setLoading(false);
 | 
					              setFileName(title as string);
 | 
				
			||||||
          }}
 | 
					              setLoading(false);
 | 
				
			||||||
        />
 | 
					            }}
 | 
				
			||||||
      )}
 | 
					          />
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -641,12 +641,13 @@ export function ChatActions(props: {
 | 
				
			|||||||
          ]}
 | 
					          ]}
 | 
				
			||||||
          onClose={() => setShowPluginSelector(false)}
 | 
					          onClose={() => setShowPluginSelector(false)}
 | 
				
			||||||
          onSelection={(s) => {
 | 
					          onSelection={(s) => {
 | 
				
			||||||
            if (s.length === 0) return;
 | 
					 | 
				
			||||||
            const plugin = s[0];
 | 
					            const plugin = s[0];
 | 
				
			||||||
            chatStore.updateCurrentSession((session) => {
 | 
					            chatStore.updateCurrentSession((session) => {
 | 
				
			||||||
              session.mask.plugin = s;
 | 
					              session.mask.plugin = s;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            showToast(plugin);
 | 
					            if (plugin) {
 | 
				
			||||||
 | 
					              showToast(plugin);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,8 @@ import React from "react";
 | 
				
			|||||||
import { useDebouncedCallback } from "use-debounce";
 | 
					import { useDebouncedCallback } from "use-debounce";
 | 
				
			||||||
import { showImageModal, FullScreen } from "./ui-lib";
 | 
					import { showImageModal, FullScreen } from "./ui-lib";
 | 
				
			||||||
import { ArtifactShareButton, HTMLPreview } from "./artifact";
 | 
					import { ArtifactShareButton, HTMLPreview } from "./artifact";
 | 
				
			||||||
 | 
					import { Plugin } from "../constant";
 | 
				
			||||||
 | 
					import { useChatStore } from "../store";
 | 
				
			||||||
export function Mermaid(props: { code: string }) {
 | 
					export function Mermaid(props: { code: string }) {
 | 
				
			||||||
  const ref = useRef<HTMLDivElement>(null);
 | 
					  const ref = useRef<HTMLDivElement>(null);
 | 
				
			||||||
  const [hasError, setHasError] = useState(false);
 | 
					  const [hasError, setHasError] = useState(false);
 | 
				
			||||||
@@ -67,6 +68,9 @@ export function PreCode(props: { children: any }) {
 | 
				
			|||||||
  const [mermaidCode, setMermaidCode] = useState("");
 | 
					  const [mermaidCode, setMermaidCode] = useState("");
 | 
				
			||||||
  const [htmlCode, setHtmlCode] = useState("");
 | 
					  const [htmlCode, setHtmlCode] = useState("");
 | 
				
			||||||
  const { height } = useWindowSize();
 | 
					  const { height } = useWindowSize();
 | 
				
			||||||
 | 
					  const chatStore = useChatStore();
 | 
				
			||||||
 | 
					  const session = chatStore.currentSession();
 | 
				
			||||||
 | 
					  const plugins = session.mask?.plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const renderArtifacts = useDebouncedCallback(() => {
 | 
					  const renderArtifacts = useDebouncedCallback(() => {
 | 
				
			||||||
    if (!ref.current) return;
 | 
					    if (!ref.current) return;
 | 
				
			||||||
@@ -87,6 +91,11 @@ export function PreCode(props: { children: any }) {
 | 
				
			|||||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
  }, [refText]);
 | 
					  }, [refText]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const enableArtifacts = useMemo(
 | 
				
			||||||
 | 
					    () => plugins?.includes(Plugin.Artifact),
 | 
				
			||||||
 | 
					    [plugins],
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <>
 | 
					    <>
 | 
				
			||||||
      <pre ref={ref}>
 | 
					      <pre ref={ref}>
 | 
				
			||||||
@@ -104,7 +113,7 @@ export function PreCode(props: { children: any }) {
 | 
				
			|||||||
      {mermaidCode.length > 0 && (
 | 
					      {mermaidCode.length > 0 && (
 | 
				
			||||||
        <Mermaid code={mermaidCode} key={mermaidCode} />
 | 
					        <Mermaid code={mermaidCode} key={mermaidCode} />
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
      {htmlCode.length > 0 && (
 | 
					      {htmlCode.length > 0 && enableArtifacts && (
 | 
				
			||||||
        <FullScreen className="no-dark html" right={70}>
 | 
					        <FullScreen className="no-dark html" right={70}>
 | 
				
			||||||
          <ArtifactShareButton
 | 
					          <ArtifactShareButton
 | 
				
			||||||
            style={{ position: "absolute", right: 20, top: 10 }}
 | 
					            style={{ position: "absolute", right: 20, top: 10 }}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user