File size: 4,832 Bytes
bcb0fad
e29580c
 
 
 
bcb0fad
6692511
8e92e61
bcb0fad
 
 
 
 
b573489
bcb0fad
 
 
 
 
b573489
bcb0fad
 
e29580c
bcb0fad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e29580c
93f259b
e29580c
 
 
 
6692511
 
 
 
 
 
 
bcb0fad
 
 
 
e29580c
 
 
 
50e5742
e29580c
 
 
 
bcb0fad
 
de9adca
 
 
 
 
 
 
 
 
 
 
 
 
ccdf544
de9adca
 
 
e29580c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
de9adca
ccdf544
 
 
 
a3ba9ae
ccdf544
 
de9adca
 
bcb0fad
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import classNames from "classnames";
import { useRef, useState } from "react";
import { FaLaptopCode } from "react-icons/fa6";
import { FaMobileAlt } from "react-icons/fa";

import { TbReload } from "react-icons/tb";
import { toast } from "react-toastify";
import { defaultHTML } from "../../../utils/consts";

function Preview({
  html,
  isResizing,
  isAiWorking,
  setView,
  ref,
}: {
  html: string;
  isResizing: boolean;
  isAiWorking: boolean;
  setView: React.Dispatch<React.SetStateAction<"editor" | "preview">>;
  ref: React.RefObject<HTMLDivElement | null>;
}) {
  const [device, setDevice] = useState<"desktop" | "mobile">("desktop");
  const iframeRef = useRef<HTMLIFrameElement | null>(null);

  const handleRefreshIframe = () => {
    if (iframeRef.current) {
      const iframe = iframeRef.current;
      const content = iframe.srcdoc;
      iframe.srcdoc = "";
      setTimeout(() => {
        iframe.srcdoc = content;
      }, 10);
    }
  };

  return (
    <div
      ref={ref}
      className={classNames(
        "w-full border-l border-gray-900 bg-white h-[calc(100dvh-49px)] lg:h-[calc(100dvh-53px)] relative transition-all duration-200",
        {
          "flex items-center justify-center": device === "mobile",
        }
      )}
      onClick={(e) => {
        if (isAiWorking) {
          e.preventDefault();
          e.stopPropagation();
          toast.warn("Please wait for the AI to finish working.");
        }
      }}
    >
      <iframe
        ref={iframeRef}
        title="output"
        className={classNames(
          "w-full select-none transition-all duration-200",
          {
            "pointer-events-none": isResizing || isAiWorking,
            "max-w-md mx-auto h-[80dvh] rounded-[64px] border-[8px] border-black shadow-2xl":
              device === "mobile",
            "h-full": device === "desktop",
          }
        )}
        srcDoc={html}
      />
      <div className="flex items-center justify-start gap-3 absolute bottom-3 lg:bottom-5 max-lg:left-3 lg:right-5">
        <button
          className="lg:hidden bg-gray-950 shadow-md text-white text-xs lg:text-sm font-medium py-2 px-3 lg:px-4 rounded-lg flex items-center gap-2 border border-gray-900 hover:brightness-150 transition-all duration-100 cursor-pointer"
          onClick={() => setView("editor")}
        >
          <FaLaptopCode className="text-sm" />
          Hide preview
        </button>
        {html === defaultHTML && (
          <a
            href="https://huggingface.co/spaces/victor/deepsite-gallery"
            target="_blank"
            className="bg-gray-200 text-gray-950 text-xs lg:text-sm font-medium py-2 px-3 lg:px-4 rounded-lg flex items-center gap-2 border border-gray-200 hover:bg-gray-300 transition-all duration-100 cursor-pointer"
          >
            🖼️ <span>DeepSite Gallery</span>
          </a>
        )}
        {html !== defaultHTML && !isAiWorking && (
          <div className="flex items-center rounded-lg p-1 bg-gray-200 relative overflow-hidden z-0 max-lg:hidden">
            <div
              className={classNames(
                "absolute left-1 top-1 rounded-md bg-black w-10 h-8 -z-[1] transition-all duration-200",
                {
                  "translate-x-full": device === "mobile",
                }
              )}
            />
            <button
              className={classNames(
                "rounded-md text-gray-500 w-10 h-8 flex items-center justify-center cursor-pointer",
                {
                  "!text-white": device === "desktop",
                  "hover:bg-gray-300/60": device !== "desktop",
                }
              )}
              onClick={() => setDevice("desktop")}
            >
              <FaLaptopCode className="text-sm" />
            </button>
            <button
              className={classNames(
                "rounded-md text-gray-500 w-10 h-8 flex items-center justify-center cursor-pointer",
                {
                  "!text-white": device === "mobile",
                  "hover:bg-gray-300/60": device !== "mobile",
                }
              )}
              onClick={() => setDevice("mobile")}
            >
              <FaMobileAlt className="text-sm" />
            </button>
          </div>
        )}
        {!isAiWorking && (
          <button
            className="bg-white lg:bg-gray-950 shadow-md text-gray-950 lg:text-white text-xs lg:text-sm font-medium py-2 px-3 lg:px-4 rounded-lg flex items-center gap-2 border border-gray-100 lg:border-gray-900 hover:brightness-150 transition-all duration-100 cursor-pointer"
            onClick={handleRefreshIframe}
          >
            <TbReload className="text-sm" />
            Refresh Preview
          </button>
        )}
      </div>
    </div>
  );
}

export default Preview;