legends810 commited on
Commit
03ff358
·
verified ·
1 Parent(s): 8026e5e

Update components/editor/index.tsx

Browse files
Files changed (1) hide show
  1. components/editor/index.tsx +47 -12
components/editor/index.tsx CHANGED
@@ -27,11 +27,10 @@ import { SaveButton } from "./save-button";
27
  import { LoadProject } from "../my-projects/load-project";
28
  import { isTheSameHtml } from "@/lib/compare-html-diff";
29
  import { ListPages } from "./pages";
30
- import { AiThinking } from "./ai-thinking"; // Import the new component
31
 
32
  export const AppEditor = ({
33
  project,
34
- initialPages,
35
  images,
36
  isNew,
37
  }: {
@@ -58,6 +57,7 @@ export const AppEditor = ({
58
  const editor = useRef<HTMLDivElement>(null);
59
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
60
  const resizer = useRef<HTMLDivElement>(null);
 
61
  const monacoRef = useRef<any>(null);
62
 
63
  const [currentTab, setCurrentTab] = useState("chat");
@@ -65,7 +65,6 @@ export const AppEditor = ({
65
  const [device, setDevice] = useState<"desktop" | "mobile">("desktop");
66
  const [isResizing, setIsResizing] = useState(false);
67
  const [isAiWorking, setIsAiWorking] = useState(false);
68
- const [aiThinking, setAiThinking] = useState<string | null>(null); // State for AI thinking text
69
  const [isEditableModeEnabled, setIsEditableModeEnabled] = useState(false);
70
  const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(
71
  null
@@ -74,14 +73,18 @@ export const AppEditor = ({
74
 
75
  const resetLayout = () => {
76
  if (!editor.current || !preview.current) return;
 
 
77
  if (window.innerWidth >= 1024) {
78
- const resizerWidth = resizer.current?.offsetWidth ?? 8;
 
79
  const availableWidth = window.innerWidth - resizerWidth;
80
- const initialEditorWidth = availableWidth / 3;
81
- const initialPreviewWidth = availableWidth - initialEditorWidth;
82
  editor.current.style.width = `${initialEditorWidth}px`;
83
  preview.current.style.width = `${initialPreviewWidth}px`;
84
  } else {
 
85
  editor.current.style.width = "";
86
  preview.current.style.width = "";
87
  }
@@ -89,9 +92,11 @@ export const AppEditor = ({
89
 
90
  const handleResize = (e: MouseEvent) => {
91
  if (!editor.current || !preview.current || !resizer.current) return;
 
92
  const resizerWidth = resizer.current.offsetWidth;
93
- const minWidth = 100;
94
  const maxWidth = window.innerWidth - resizerWidth - minWidth;
 
95
  const editorWidth = e.clientX;
96
  const clampedEditorWidth = Math.max(
97
  minWidth,
@@ -99,6 +104,7 @@ export const AppEditor = ({
99
  );
100
  const calculatedPreviewWidth =
101
  window.innerWidth - clampedEditorWidth - resizerWidth;
 
102
  editor.current.style.width = `${clampedEditorWidth}px`;
103
  preview.current.style.width = `${calculatedPreviewWidth}px`;
104
  };
@@ -134,12 +140,12 @@ export const AppEditor = ({
134
  removeHtmlStorage();
135
  toast.warning("Previous HTML content restored from local storage.");
136
  }
 
137
  resetLayout();
138
  if (!resizer.current) return;
139
  resizer.current.addEventListener("mousedown", handleMouseDown);
140
  window.addEventListener("resize", resetLayout);
141
  });
142
-
143
  useUnmount(() => {
144
  document.removeEventListener("mousemove", handleResize);
145
  document.removeEventListener("mouseup", handleMouseUp);
@@ -149,6 +155,7 @@ export const AppEditor = ({
149
  window.removeEventListener("resize", resetLayout);
150
  });
151
 
 
152
  useEvent("beforeunload", (e) => {
153
  if (isAiWorking || !isTheSameHtml(currentPageData?.html)) {
154
  e.preventDefault();
@@ -158,12 +165,15 @@ export const AppEditor = ({
158
 
159
  useUpdateEffect(() => {
160
  if (currentTab === "chat") {
 
161
  resetLayout();
 
162
  if (resizer.current) {
163
  resizer.current.addEventListener("mousedown", handleMouseDown);
164
  }
165
  } else {
166
  if (preview.current) {
 
167
  preview.current.style.width = "100%";
168
  }
169
  }
@@ -190,6 +200,7 @@ export const AppEditor = ({
190
  router.push(`/projects/${project.space_id}`);
191
  }}
192
  />
 
193
  {project?._id ? (
194
  <SaveButton pages={pages} prompts={prompts} />
195
  ) : (
@@ -243,25 +254,29 @@ export const AppEditor = ({
243
  toast.success("HTML copied to clipboard!");
244
  }}
245
  />
246
- {aiThinking && <AiThinking text={aiThinking} />}
247
  <Editor
248
  defaultLanguage="html"
249
  theme="vs-dark"
250
  className={classNames(
251
  "h-full bg-neutral-900 transition-all duration-200 absolute left-0 top-0",
252
- { "pointer-events-none": isAiWorking }
 
 
253
  )}
254
  options={{
255
  colorDecorators: true,
256
  fontLigatures: true,
257
  theme: "vs-dark",
258
  minimap: { enabled: false },
259
- scrollbar: { horizontal: "hidden" },
 
 
260
  wordWrap: "on",
261
  }}
262
  value={currentPageData.html}
263
  onChange={(value) => {
264
  const newValue = value ?? "";
 
265
  setPages((prev) =>
266
  prev.map((page) =>
267
  page.path === currentPageData.path
@@ -282,7 +297,6 @@ export const AppEditor = ({
282
  currentPage={currentPageData}
283
  htmlHistory={htmlHistory}
284
  previousPrompts={prompts}
285
- setAiThinking={setAiThinking} // Pass the setter function
286
  onSuccess={(newPages, p: string) => {
287
  const currentHistory = [...htmlHistory];
288
  currentHistory.unshift({
@@ -293,9 +307,30 @@ export const AppEditor = ({
293
  setHtmlHistory(currentHistory);
294
  setSelectedElement(null);
295
  setSelectedFiles([]);
 
296
  if (window.innerWidth <= 1024) {
297
  setCurrentTab("preview");
298
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }}
300
  setPages={setPages}
301
  pages={pages}
 
27
  import { LoadProject } from "../my-projects/load-project";
28
  import { isTheSameHtml } from "@/lib/compare-html-diff";
29
  import { ListPages } from "./pages";
 
30
 
31
  export const AppEditor = ({
32
  project,
33
+ pages: initialPages,
34
  images,
35
  isNew,
36
  }: {
 
57
  const editor = useRef<HTMLDivElement>(null);
58
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
59
  const resizer = useRef<HTMLDivElement>(null);
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
  const monacoRef = useRef<any>(null);
62
 
63
  const [currentTab, setCurrentTab] = useState("chat");
 
65
  const [device, setDevice] = useState<"desktop" | "mobile">("desktop");
66
  const [isResizing, setIsResizing] = useState(false);
67
  const [isAiWorking, setIsAiWorking] = useState(false);
 
68
  const [isEditableModeEnabled, setIsEditableModeEnabled] = useState(false);
69
  const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(
70
  null
 
73
 
74
  const resetLayout = () => {
75
  if (!editor.current || !preview.current) return;
76
+
77
+ // lg breakpoint is 1024px based on useBreakpoint definition and Tailwind defaults
78
  if (window.innerWidth >= 1024) {
79
+ // Set initial 1/3 - 2/3 sizes for large screens, accounting for resizer width
80
+ const resizerWidth = resizer.current?.offsetWidth ?? 8; // w-2 = 0.5rem = 8px
81
  const availableWidth = window.innerWidth - resizerWidth;
82
+ const initialEditorWidth = availableWidth / 3; // Editor takes 1/3 of space
83
+ const initialPreviewWidth = availableWidth - initialEditorWidth; // Preview takes 2/3
84
  editor.current.style.width = `${initialEditorWidth}px`;
85
  preview.current.style.width = `${initialPreviewWidth}px`;
86
  } else {
87
+ // Remove inline styles for smaller screens, let CSS flex-col handle it
88
  editor.current.style.width = "";
89
  preview.current.style.width = "";
90
  }
 
92
 
93
  const handleResize = (e: MouseEvent) => {
94
  if (!editor.current || !preview.current || !resizer.current) return;
95
+
96
  const resizerWidth = resizer.current.offsetWidth;
97
+ const minWidth = 100; // Minimum width for editor/preview
98
  const maxWidth = window.innerWidth - resizerWidth - minWidth;
99
+
100
  const editorWidth = e.clientX;
101
  const clampedEditorWidth = Math.max(
102
  minWidth,
 
104
  );
105
  const calculatedPreviewWidth =
106
  window.innerWidth - clampedEditorWidth - resizerWidth;
107
+
108
  editor.current.style.width = `${clampedEditorWidth}px`;
109
  preview.current.style.width = `${calculatedPreviewWidth}px`;
110
  };
 
140
  removeHtmlStorage();
141
  toast.warning("Previous HTML content restored from local storage.");
142
  }
143
+
144
  resetLayout();
145
  if (!resizer.current) return;
146
  resizer.current.addEventListener("mousedown", handleMouseDown);
147
  window.addEventListener("resize", resetLayout);
148
  });
 
149
  useUnmount(() => {
150
  document.removeEventListener("mousemove", handleResize);
151
  document.removeEventListener("mouseup", handleMouseUp);
 
155
  window.removeEventListener("resize", resetLayout);
156
  });
157
 
158
+ // Prevent accidental navigation away when AI is working or content has changed
159
  useEvent("beforeunload", (e) => {
160
  if (isAiWorking || !isTheSameHtml(currentPageData?.html)) {
161
  e.preventDefault();
 
165
 
166
  useUpdateEffect(() => {
167
  if (currentTab === "chat") {
168
+ // Reset editor width when switching to reasoning tab
169
  resetLayout();
170
+ // re-add the event listener for resizing
171
  if (resizer.current) {
172
  resizer.current.addEventListener("mousedown", handleMouseDown);
173
  }
174
  } else {
175
  if (preview.current) {
176
+ // Reset preview width when switching to preview tab
177
  preview.current.style.width = "100%";
178
  }
179
  }
 
200
  router.push(`/projects/${project.space_id}`);
201
  }}
202
  />
203
+ {/* for these buttons pass the whole pages */}
204
  {project?._id ? (
205
  <SaveButton pages={pages} prompts={prompts} />
206
  ) : (
 
254
  toast.success("HTML copied to clipboard!");
255
  }}
256
  />
 
257
  <Editor
258
  defaultLanguage="html"
259
  theme="vs-dark"
260
  className={classNames(
261
  "h-full bg-neutral-900 transition-all duration-200 absolute left-0 top-0",
262
+ {
263
+ "pointer-events-none": isAiWorking,
264
+ }
265
  )}
266
  options={{
267
  colorDecorators: true,
268
  fontLigatures: true,
269
  theme: "vs-dark",
270
  minimap: { enabled: false },
271
+ scrollbar: {
272
+ horizontal: "hidden",
273
+ },
274
  wordWrap: "on",
275
  }}
276
  value={currentPageData.html}
277
  onChange={(value) => {
278
  const newValue = value ?? "";
279
+ // setHtml(newValue);
280
  setPages((prev) =>
281
  prev.map((page) =>
282
  page.path === currentPageData.path
 
297
  currentPage={currentPageData}
298
  htmlHistory={htmlHistory}
299
  previousPrompts={prompts}
 
300
  onSuccess={(newPages, p: string) => {
301
  const currentHistory = [...htmlHistory];
302
  currentHistory.unshift({
 
307
  setHtmlHistory(currentHistory);
308
  setSelectedElement(null);
309
  setSelectedFiles([]);
310
+ // if xs or sm
311
  if (window.innerWidth <= 1024) {
312
  setCurrentTab("preview");
313
  }
314
+ // if (updatedLines && updatedLines?.length > 0) {
315
+ // const decorations = updatedLines.map((line) => ({
316
+ // range: new monacoRef.current.Range(
317
+ // line[0],
318
+ // 1,
319
+ // line[1],
320
+ // 1
321
+ // ),
322
+ // options: {
323
+ // inlineClassName: "matched-line",
324
+ // },
325
+ // }));
326
+ // setTimeout(() => {
327
+ // editorRef?.current
328
+ // ?.getModel()
329
+ // ?.deltaDecorations([], decorations);
330
+
331
+ // editorRef.current?.revealLine(updatedLines[0][0]);
332
+ // }, 100);
333
+ // }
334
  }}
335
  setPages={setPages}
336
  pages={pages}