UI changes
Browse files- README.md +1 -1
- public/arrow.svg +10 -0
- src/components/App.tsx +14 -16
- src/components/deploy-button/deploy-button.tsx +17 -1
- src/components/header/header.tsx +24 -3
- src/utils/consts.ts +17 -1
README.md
CHANGED
@@ -7,7 +7,7 @@ sdk: docker
|
|
7 |
pinned: true
|
8 |
app_port: 5173
|
9 |
license: mit
|
10 |
-
short_description:
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
7 |
pinned: true
|
8 |
app_port: 5173
|
9 |
license: mit
|
10 |
+
short_description: Imagine and Share in 1-Click
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
public/arrow.svg
ADDED
|
src/components/App.tsx
CHANGED
@@ -2,12 +2,7 @@ import { useRef, useState } from "react";
|
|
2 |
import Editor from "@monaco-editor/react";
|
3 |
import classNames from "classnames";
|
4 |
import { editor } from "monaco-editor";
|
5 |
-
import {
|
6 |
-
useMount,
|
7 |
-
useUnmount,
|
8 |
-
useEvent,
|
9 |
-
useLocalStorage,
|
10 |
-
} from "react-use";
|
11 |
import { toast } from "react-toastify";
|
12 |
|
13 |
import Header from "./header/header";
|
@@ -18,7 +13,6 @@ import AskAI from "./ask-ai/ask-ai";
|
|
18 |
import { Auth } from "../utils/types";
|
19 |
import Preview from "./preview/preview";
|
20 |
|
21 |
-
|
22 |
function App() {
|
23 |
const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
|
24 |
|
@@ -62,8 +56,8 @@ function App() {
|
|
62 |
preview.current.style.width = `${initialPreviewWidth}px`;
|
63 |
} else {
|
64 |
// Remove inline styles for smaller screens, let CSS flex-col handle it
|
65 |
-
editor.current.style.width =
|
66 |
-
preview.current.style.width =
|
67 |
}
|
68 |
};
|
69 |
|
@@ -73,15 +67,19 @@ function App() {
|
|
73 |
*/
|
74 |
const handleResize = (e: MouseEvent) => {
|
75 |
if (!editor.current || !preview.current || !resizer.current) return;
|
76 |
-
|
77 |
const resizerWidth = resizer.current.offsetWidth;
|
78 |
const minWidth = 100; // Minimum width for editor/preview
|
79 |
const maxWidth = window.innerWidth - resizerWidth - minWidth;
|
80 |
-
|
81 |
const editorWidth = e.clientX;
|
82 |
-
const clampedEditorWidth = Math.max(
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
85 |
editor.current.style.width = `${clampedEditorWidth}px`;
|
86 |
preview.current.style.width = `${calculatedPreviewWidth}px`;
|
87 |
};
|
@@ -110,7 +108,7 @@ function App() {
|
|
110 |
useMount(() => {
|
111 |
// Fetch user data
|
112 |
fetchMe();
|
113 |
-
|
114 |
// Restore content from storage if available
|
115 |
if (htmlStorage) {
|
116 |
removeHtmlStorage();
|
@@ -138,7 +136,7 @@ function App() {
|
|
138 |
|
139 |
return (
|
140 |
<div className="h-screen bg-gray-950 font-sans overflow-hidden">
|
141 |
-
<Header>
|
142 |
<DeployButton html={html} error={error} auth={auth} />
|
143 |
</Header>
|
144 |
<main className="max-lg:flex-col flex w-full">
|
|
|
2 |
import Editor from "@monaco-editor/react";
|
3 |
import classNames from "classnames";
|
4 |
import { editor } from "monaco-editor";
|
5 |
+
import { useMount, useUnmount, useEvent, useLocalStorage } from "react-use";
|
|
|
|
|
|
|
|
|
|
|
6 |
import { toast } from "react-toastify";
|
7 |
|
8 |
import Header from "./header/header";
|
|
|
13 |
import { Auth } from "../utils/types";
|
14 |
import Preview from "./preview/preview";
|
15 |
|
|
|
16 |
function App() {
|
17 |
const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
|
18 |
|
|
|
56 |
preview.current.style.width = `${initialPreviewWidth}px`;
|
57 |
} else {
|
58 |
// Remove inline styles for smaller screens, let CSS flex-col handle it
|
59 |
+
editor.current.style.width = "";
|
60 |
+
preview.current.style.width = "";
|
61 |
}
|
62 |
};
|
63 |
|
|
|
67 |
*/
|
68 |
const handleResize = (e: MouseEvent) => {
|
69 |
if (!editor.current || !preview.current || !resizer.current) return;
|
70 |
+
|
71 |
const resizerWidth = resizer.current.offsetWidth;
|
72 |
const minWidth = 100; // Minimum width for editor/preview
|
73 |
const maxWidth = window.innerWidth - resizerWidth - minWidth;
|
74 |
+
|
75 |
const editorWidth = e.clientX;
|
76 |
+
const clampedEditorWidth = Math.max(
|
77 |
+
minWidth,
|
78 |
+
Math.min(editorWidth, maxWidth)
|
79 |
+
);
|
80 |
+
const calculatedPreviewWidth =
|
81 |
+
window.innerWidth - clampedEditorWidth - resizerWidth;
|
82 |
+
|
83 |
editor.current.style.width = `${clampedEditorWidth}px`;
|
84 |
preview.current.style.width = `${calculatedPreviewWidth}px`;
|
85 |
};
|
|
|
108 |
useMount(() => {
|
109 |
// Fetch user data
|
110 |
fetchMe();
|
111 |
+
|
112 |
// Restore content from storage if available
|
113 |
if (htmlStorage) {
|
114 |
removeHtmlStorage();
|
|
|
136 |
|
137 |
return (
|
138 |
<div className="h-screen bg-gray-950 font-sans overflow-hidden">
|
139 |
+
<Header onReset={() => setHtml(defaultHTML)}>
|
140 |
<DeployButton html={html} error={error} auth={auth} />
|
141 |
</Header>
|
142 |
<main className="max-lg:flex-col flex w-full">
|
src/components/deploy-button/deploy-button.tsx
CHANGED
@@ -8,6 +8,20 @@ import Loading from "../loading/loading";
|
|
8 |
import Login from "../login/login";
|
9 |
import { Auth } from "../../utils/types";
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
function DeployButton({
|
12 |
html,
|
13 |
error = false,
|
@@ -43,7 +57,9 @@ function DeployButton({
|
|
43 |
const response = await request.json();
|
44 |
if (response.ok) {
|
45 |
toast.success(
|
46 |
-
|
|
|
|
|
47 |
);
|
48 |
setPath(response.path);
|
49 |
} else {
|
|
|
8 |
import Login from "../login/login";
|
9 |
import { Auth } from "../../utils/types";
|
10 |
|
11 |
+
const MsgToast = ({ url }: { url: string }) => (
|
12 |
+
<div className="w-full flex items-center justify-center gap-3">
|
13 |
+
Your space is live!
|
14 |
+
<button
|
15 |
+
className="bg-black text-sm block text-white rounded-md px-3 py-1.5 hover:bg-gray-900 cursor-pointer"
|
16 |
+
onClick={() => {
|
17 |
+
window.open(url, "_blank");
|
18 |
+
}}
|
19 |
+
>
|
20 |
+
See Space
|
21 |
+
</button>
|
22 |
+
</div>
|
23 |
+
);
|
24 |
+
|
25 |
function DeployButton({
|
26 |
html,
|
27 |
error = false,
|
|
|
57 |
const response = await request.json();
|
58 |
if (response.ok) {
|
59 |
toast.success(
|
60 |
+
<MsgToast
|
61 |
+
url={`https://huggingface.co/spaces/${response.path ?? path}`}
|
62 |
+
/>
|
63 |
);
|
64 |
setPath(response.path);
|
65 |
} else {
|
src/components/header/header.tsx
CHANGED
@@ -1,7 +1,21 @@
|
|
1 |
-
import Logo from "@/assets/logo.svg";
|
2 |
import { ReactNode } from "react";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
-
function Header({ children }: { children?: ReactNode }) {
|
5 |
return (
|
6 |
<header className="border-b border-gray-900 px-3 lg:px-6 py-2 flex justify-between items-center">
|
7 |
<div className="flex items-center justify-start gap-3">
|
@@ -14,8 +28,15 @@ function Header({ children }: { children?: ReactNode }) {
|
|
14 |
DeepSite
|
15 |
</h1>
|
16 |
<p className="text-gray-700 max-md:hidden">|</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
<p className="text-gray-500 text-sm max-md:hidden">
|
18 |
-
|
19 |
</p>
|
20 |
</div>
|
21 |
{children}
|
|
|
|
|
1 |
import { ReactNode } from "react";
|
2 |
+
import { MdAdd } from "react-icons/md";
|
3 |
+
|
4 |
+
import Logo from "@/assets/logo.svg";
|
5 |
+
|
6 |
+
function Header({
|
7 |
+
onReset,
|
8 |
+
children,
|
9 |
+
}: {
|
10 |
+
onReset: () => void;
|
11 |
+
children?: ReactNode;
|
12 |
+
}) {
|
13 |
+
const handleConfirm = () => {
|
14 |
+
if (window.confirm("You're about to reset the editor. Are you sure?")) {
|
15 |
+
onReset();
|
16 |
+
}
|
17 |
+
};
|
18 |
|
|
|
19 |
return (
|
20 |
<header className="border-b border-gray-900 px-3 lg:px-6 py-2 flex justify-between items-center">
|
21 |
<div className="flex items-center justify-start gap-3">
|
|
|
28 |
DeepSite
|
29 |
</h1>
|
30 |
<p className="text-gray-700 max-md:hidden">|</p>
|
31 |
+
<button
|
32 |
+
className="max-md:hidden relative cursor-pointer flex-none flex items-center justify-center rounded-md text-xs font-semibold leading-5 py-1.5 px-4 hover:bg-gray-100 text-gray-950 shadow-sm dark:shadow-highlight/20 bg-white"
|
33 |
+
onClick={handleConfirm}
|
34 |
+
>
|
35 |
+
<MdAdd className="text-gray-800 mr-1 text-base" />
|
36 |
+
New Project
|
37 |
+
</button>
|
38 |
<p className="text-gray-500 text-sm max-md:hidden">
|
39 |
+
Imagine and Share in 1-Click
|
40 |
</p>
|
41 |
</div>
|
42 |
{children}
|
src/utils/consts.ts
CHANGED
@@ -13,12 +13,28 @@ export const defaultHTML = `<!DOCTYPE html>
|
|
13 |
font-family: "Arial", sans-serif;
|
14 |
text-align: center;
|
15 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
</style>
|
17 |
</head>
|
18 |
<body>
|
19 |
<h1>
|
20 |
-
|
|
|
21 |
</h1>
|
|
|
22 |
<script></script>
|
23 |
</body>
|
24 |
</html>
|
|
|
13 |
font-family: "Arial", sans-serif;
|
14 |
text-align: center;
|
15 |
}
|
16 |
+
.arrow {
|
17 |
+
position: absolute;
|
18 |
+
bottom: 32px;
|
19 |
+
left: 0px;
|
20 |
+
width: 100px;
|
21 |
+
transform: rotate(30deg);
|
22 |
+
}
|
23 |
+
h1 {
|
24 |
+
font-size: 50px;
|
25 |
+
}
|
26 |
+
h1 span {
|
27 |
+
color: #acacac;
|
28 |
+
font-size: 32px;
|
29 |
+
}
|
30 |
</style>
|
31 |
</head>
|
32 |
<body>
|
33 |
<h1>
|
34 |
+
<span>I'm ready to work,</span><br />
|
35 |
+
Ask me anything.
|
36 |
</h1>
|
37 |
+
<img src="/arrow.svg" class="arrow" />
|
38 |
<script></script>
|
39 |
</body>
|
40 |
</html>
|