add fullscreen button on artifact component

This commit is contained in:
lloydzhou 2024-07-25 15:10:17 +08:00
parent 47b33f2b17
commit 763fc89b29
2 changed files with 49 additions and 13 deletions

View File

@ -6,13 +6,13 @@ import RehypeKatex from "rehype-katex";
import RemarkGfm from "remark-gfm"; import RemarkGfm from "remark-gfm";
import RehypeHighlight from "rehype-highlight"; import RehypeHighlight from "rehype-highlight";
import { useRef, useState, RefObject, useEffect, useMemo } from "react"; import { useRef, useState, RefObject, useEffect, useMemo } from "react";
import { copyToClipboard } from "../utils"; import { copyToClipboard, useWindowSize } from "../utils";
import mermaid from "mermaid"; import mermaid from "mermaid";
import LoadingIcon from "../icons/three-dots.svg"; import LoadingIcon from "../icons/three-dots.svg";
import React from "react"; import React from "react";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
import { showImageModal } from "./ui-lib"; import { showImageModal, FullScreen } from "./ui-lib";
import { ArtifactShareButton, HTMLPreview } from "./artifact"; import { ArtifactShareButton, HTMLPreview } from "./artifact";
export function Mermaid(props: { code: string }) { export function Mermaid(props: { code: string }) {
@ -66,6 +66,7 @@ export function PreCode(props: { children: any }) {
const refText = ref.current?.innerText; const refText = ref.current?.innerText;
const [mermaidCode, setMermaidCode] = useState(""); const [mermaidCode, setMermaidCode] = useState("");
const [htmlCode, setHtmlCode] = useState(""); const [htmlCode, setHtmlCode] = useState("");
const { height } = useWindowSize();
const renderArtifacts = useDebouncedCallback(() => { const renderArtifacts = useDebouncedCallback(() => {
if (!ref.current) return; if (!ref.current) return;
@ -104,20 +105,17 @@ export function PreCode(props: { children: any }) {
<Mermaid code={mermaidCode} key={mermaidCode} /> <Mermaid code={mermaidCode} key={mermaidCode} />
)} )}
{htmlCode.length > 0 && ( {htmlCode.length > 0 && (
<div <FullScreen className="no-dark html" right={60}>
className="no-dark html"
style={{
overflow: "auto",
position: "relative",
}}
onClick={(e) => e.stopPropagation()}
>
<ArtifactShareButton <ArtifactShareButton
style={{ position: "absolute", right: 10, top: 10 }} style={{ position: "absolute", right: 10, top: 10 }}
getCode={() => htmlCode} getCode={() => htmlCode}
/> />
<HTMLPreview code={htmlCode} /> <HTMLPreview
</div> code={htmlCode}
autoHeight={!document.fullscreenElement}
height={!document.fullscreenElement ? 600 : height}
/>
</FullScreen>
)} )}
</> </>
); );

View File

@ -13,7 +13,13 @@ import MinIcon from "../icons/min.svg";
import Locale from "../locales"; import Locale from "../locales";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import React, { HTMLProps, useEffect, useState } from "react"; import React, {
HTMLProps,
useEffect,
useState,
useCallback,
useRef,
} from "react";
import { IconButton } from "./button"; import { IconButton } from "./button";
export function Popover(props: { export function Popover(props: {
@ -488,3 +494,35 @@ export function Selector<T>(props: {
</div> </div>
); );
} }
export function FullScreen(props: any) {
const { children, right = 10, top = 10, ...rest } = props;
const ref = useRef<HTMLDivElement>();
const [fullScreen, setFullScreen] = useState(false);
const toggleFullscreen = useCallback(() => {
if (!document.fullscreenElement) {
ref.current?.requestFullscreen();
} else {
document.exitFullscreen();
}
}, []);
useEffect(() => {
document.addEventListener("fullscreenchange", (e) => {
if (e.target === ref.current) {
setFullScreen(!!document.fullscreenElement);
}
});
}, []);
return (
<div ref={ref} style={{ position: "relative" }} {...rest}>
<div style={{ position: "absolute", right, top }}>
<IconButton
icon={fullScreen ? <MinIcon /> : <MaxIcon />}
onClick={toggleFullscreen}
bordered
/>
</div>
{children}
</div>
);
}