Browse Source

add fullscreen button on artifact component

lloydzhou 1 year ago
parent
commit
763fc89b29
2 changed files with 49 additions and 13 deletions
  1. 10 12
      app/components/markdown.tsx
  2. 39 1
      app/components/ui-lib.tsx

+ 10 - 12
app/components/markdown.tsx

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

+ 39 - 1
app/components/ui-lib.tsx

@@ -13,7 +13,13 @@ import MinIcon from "../icons/min.svg";
 import Locale from "../locales";
 
 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";
 
 export function Popover(props: {
@@ -488,3 +494,35 @@ export function Selector<T>(props: {
     </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>
+  );
+}