PageSourceSearch

https://www.hamienet.com/assets/FileSystem-CXs84fOI.js

js hamienet.com collected 2026-10-02 05:01:44 UTC 23,163 bytes, 321 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { a as api } from "./index-w5lXls15.js";
3import { cl as HardDrive, cf as Plus, cd as Save, bN as History, b7 as Check, c2 as Copy, b2 as Upload, bM as Clock, c4 as RotateCcw, bi as Sparkles, aW as X, cC as ChevronDown, bF as ChevronRight, b4 as FolderOpen, du as Folder, fk as FileCode, fX as FileType, fY as FileBraces, b0 as FileText, d9 as Image } from "./vendor-D0P4XgNj.js";
4import "./vendor-i18n-BC7ZMXWQ.js";
5const buildFileTree = (files) => {
6  const root = [];
7  files.forEach((file) => {
8    const parts = file.path.split("/").filter((p) => p);
9    let currentLevel = root;
10    parts.forEach((part, index) => {
11      const isFile = index === parts.length - 1;
12      const existingNode = currentLevel.find((n) => n.name === part);
13      if (existingNode) {
14        if (!isFile && existingNode.type === "folder") {
15          currentLevel = existingNode.children;
16        }
17      } else {
18        const newNode = {
19          name: part,
20          path: "/" + parts.slice(0, index + 1).join("/"),
21          type: isFile ? "file" : "folder",
22          children: [],
23          file: isFile ? file : void 0
24        };
25        currentLevel.push(newNode);
26        if (!isFile) {
27          currentLevel = newNode.children;
28        }
29      }
30    });
31  });
32  const sortNodes = (nodes) => {
33    nodes.sort((a, b) => {
34      if (a.type === b.type) return a.name.localeCompare(b.name);
35      return a.type === "folder" ? -1 : 1;
36    });
37    nodes.forEach((n) => {
38      if (n.children.length > 0) sortNodes(n.children);
39    });
40  };
41  sortNodes(root);
42  return root;
43};
44const getFileIcon = (filename, type) => {
45  if (filename.endsWith(".tsx") || filename.endsWith(".ts")) return /* @__PURE__ */ jsxRuntimeExports.jsx(FileCode, { size: 14, className: "text-blue-500" });
46  if (filename.endsWith(".css")) return /* @__PURE__ */ jsxRuntimeExports.jsx(FileType, { size: 14, className: "text-sky-400" });
47  if (filename.endsWith(".json")) return /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { size: 14, className: "text-yellow-500" });
48  if (filename.endsWith(".html")) return /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { size: 14, className: "text-orange-500" });
49  if (filename.endsWith(".py")) return /* @__PURE__ */ jsxRuntimeExports.jsx(FileCode, { size: 14, className: "text-green-500" });
50  if (type === "image") return /* @__PURE__ */ jsxRuntimeExports.jsx(Image, { size: 14, className: "text-purple-500" });
51  return /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { size: 14, className: "text-zinc-500" });
52};
53const FileExplorer = ({ refreshTrigger, filterType = "all", initialPath }) => {
54  const [files, setFiles] = reactExports.useState([]);
55  const [selectedFile, setSelectedFile] = reactExports.useState(null);
56  const [isMockMode, setIsMockMode] = reactExports.useState(false);
57  const [editContent, setEditContent] = reactExports.useState("");
58  const [isEditing, setIsEditing] = reactExports.useState(false);
59  const [showHistory, setShowHistory] = reactExports.useState(false);
60  const [showUploadModal, setShowUploadModal] = reactExports.useState(false);
61  const [showCreateModal, setShowCreateModal] = reactExports.useState(false);
62  const [newCodeInput, setNewCodeInput] = reactExports.useState("");
63  const [newFileName, setNewFileName] = reactExports.useState("");
64  const [newFileFolder, setNewFileFolder] = reactExports.useState("/web/src/pages/AdminModules/");
65  const [copied, setCopied] = reactExports.useState(false);
66  const [expandedFolders, setExpandedFolders] = reactExports.useState(/* @__PURE__ */ new Set(["/", "/web", "/web/src", "/web/src/pages", "/web/src/pages/AdminModules"]));
67  const [localRefreshTrigger, setLocalRefreshTrigger] = reactExports.useState(0);
68  const refresh = () => setLocalRefreshTrigger((prev) => prev + 1);
69  reactExports.useEffect(() => {
70    const fetchFiles = async () => {
71      const data = await api.getFileSystem();
72      setFiles(data);
73    };
74    fetchFiles();
75  }, [refreshTrigger, localRefreshTrigger]);
76  reactExports.useEffect(() => {
77    if (initialPath) {
78      const f = files.find((f2) => f2.path === initialPath);
79      if (f) {
80        setSelectedFile(f);
81        setEditContent(f.content);
82        const parts = initialPath.split("/").filter((p) => p);
83        const pathsToExpand = new Set(expandedFolders);
84        let currentPath = "";
85        parts.slice(0, -1).forEach((part) => {
86          currentPath += "/" + part;
87          pathsToExpand.add(currentPath);
88        });
89        setExpandedFolders(pathsToExpand);
90      }
91    }
92  }, [initialPath, files]);
93  const filteredFiles = reactExports.useMemo(() => files.filter((f) => {
94    if (filterType === "all") return true;
95    if (filterType === "module") return f.isModule;
96    if (filterType === "image") return f.type === "image";
97    return f.type === filterType;
98  }), [files, filterType]);
99  const fileTree = reactExports.useMemo(() => buildFileTree(filteredFiles), [filteredFiles]);
100  const handleSelectFile = (file) => {
101    setSelectedFile(file);
102    setEditContent(file.content);
103    setIsEditing(false);
104    setShowHistory(false);
105  };
106  const toggleFolder = (path) => {
107    setExpandedFolders((prev) => {
108      const next = new Set(prev);
109      if (next.has(path)) next.delete(path);
110      else next.add(path);
111      return next;
112    });
113  };
114  const handleCopyForGemini = () => {
115    if (selectedFile) {
116      const prompt = `System Prompt: You are an expert developer. Update the following module code based on the user's request.
117Module: ${selectedFile.path}
118Description: ${selectedFile.description || "No description"}
119
120Current Code:
121${selectedFile.content}`;
122      navigator.clipboard.writeText(prompt);
123      setCopied(true);
124      setTimeout(() => setCopied(false), 2e3);
125    }
126  };
127  const handleSave = async () => {
128    if (!selectedFile) return;
129    try {
130      await api.commitDevAgentFile({ [selectedFile.path]: editContent }, "Manual Edit");
131      refresh();
132      setIsEditing(false);
133    } catch (e) {
134      console.error("Save failed", e);
135      alert("Failed to save file");
136    }
137  };
138  const handleApplyUpload = async () => {
139    if (!selectedFile || !newCodeInput) return;
140    try {
141      await api.commitDevAgentFile({ [selectedFile.path]: newCodeInput }, "AI Update");
142      refresh();
143      setShowUploadModal(false);
144      setNewCodeInput("");
145    } catch (e) {
146      console.error("Upload apply failed", e);
147      alert("Failed to apply update");
148    }
149  };
150  const handleCreateFile = async () => {
151    if (!newFileName) return;
152    const fullPath = `${newFileFolder.replace(/\/$/, "")}/${newFileName.replace(/^\//, "")}`;
153    const content = `import React from 'react';
154
155export default function ${newFileName.split(".")[0]}() {
156  return <div>New Module</div>;
157}`;
158    try {
159      await api.commitDevAgentFile({ [fullPath]: content }, "Create new file");
160      refresh();
161      setShowCreateModal(false);
162      setNewFileName("");
163    } catch (e) {
164      console.error("Create file failed", e);
165      alert("Failed to create file");
166    }
167  };
168  const handleRestore = async (version) => {
169    if (!confirm(`Restore version from ${version.timestamp}?`)) return;
170    if (!selectedFile) return;
171    try {
172      await api.commitDevAgentFile({ [selectedFile.path]: version.content }, `Restored to ${version.timestamp}`);
173      refresh();
174      setShowHistory(false);
175    } catch (e) {
176      console.error("Restore failed", e);
177      alert("Failed to restore version");
178    }
179  };
180  const renderTreeNodes = (nodes, depth = 0) => {
181    return nodes.map((node) => {
182      var _a;
183      const isExpanded = expandedFolders.has(node.path);
184      const isSelected = (selectedFile == null ? void 0 : selectedFile.path) === node.path;
185      return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
186        /* @__PURE__ */ jsxRuntimeExports.jsxs(
187          "div",
188          {
189            className: `flex items-center gap-1.5 px-2 py-1 cursor-pointer select-none text-xs transition-colors whitespace-nowrap ${isSelected ? "bg-indigo-100 dark:bg-indigo-900/40 text-indigo-700 dark:text-indigo-300" : "text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800"}`,
190            style: { paddingLeft: `${depth * 16 + 8}px` },
191            onClick: () => node.type === "folder" ? toggleFolder(node.path) : handleSelectFile(node.file),
192            children: [
193              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "opacity-50", children: node.type === "folder" ? isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 12 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 12 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-3" }) }),
194              node.type === "folder" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 dark:text-zinc-400", children: isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { size: 14, className: "fill-zinc-200 dark:fill-zinc-700 text-zinc-400" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { size: 14, className: "fill-zinc-200 dark:fill-zinc-700 text-zinc-400" }) }) : getFileIcon(node.name, ((_a = node.file) == null ? void 0 : _a.type) || "file"),
195              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `truncate ${node.type === "folder" ? "font-bold" : ""}`, children: node.name })
196            ]
197          }
198        ),
199        node.type === "folder" && isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: renderTreeNodes(node.children, depth + 1) })
200      ] }, node.path);
201    });
202  };
203  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 flex flex-col h-full overflow-hidden shadow-sm", children: [
204    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-14 border-b border-zinc-200 dark:border-zinc-800 flex items-center justify-between px-4 bg-zinc-50 dark:bg-zinc-950 shrink-0", children: [
205      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
206        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-bold text-sm text-zinc-500 uppercase tracking-wider flex items-center gap-2", children: [
207          /* @__PURE__ */ jsxRuntimeExports.jsx(HardDrive, { size: 16 }),
208          " File System"
209        ] }),
210        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowCreateModal(true), className: "p-1 hover:bg-zinc-200 dark:hover:bg-zinc-800 rounded text-indigo-600 dark:text-indigo-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { size: 16 }) })
211      ] }),
212      selectedFile && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
213        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-mono text-zinc-500 mr-2 hidden md:inline", children: selectedFile.path }),
214        isEditing ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
215          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setIsEditing(false), className: "px-3 py-1.5 rounded-lg text-xs font-bold text-zinc-600 hover:bg-zinc-200 dark:text-zinc-400 dark:hover:bg-zinc-800", children: "Cancel" }),
216          /* @__P
216URE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleSave, className: "px-3 py-1.5 rounded-lg text-xs font-bold bg-indigo-600 text-white hover:bg-indigo-700 flex items-center gap-1", children: [
217            /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { size: 12 }),
218            " Save"
219          ] })
220        ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setIsEditing(true), className: "px-3 py-1.5 rounded-lg text-xs font-bold bg-zinc-200 dark:bg-zinc-800 hover:bg-zinc-300 dark:hover:bg-zinc-700 text-zinc-700 dark:text-zinc-300", children: "Edit" })
221      ] })
222    ] }),
223    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex min-h-0 overflow-hidden", children: [
224      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-64 border-r border-zinc-200 dark:border-zinc-800 bg-zinc-50/50 dark:bg-zinc-950/30 flex flex-col shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-y-auto flex-1 custom-scrollbar py-2", children: renderTreeNodes(fileTree) }) }),
225      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex flex-col bg-white dark:bg-zinc-900 relative min-w-0", children: selectedFile ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
226        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-10 border-b border-zinc-200 dark:border-zinc-800 flex items-center justify-between px-4 bg-zinc-50 dark:bg-zinc-950", children: [
227          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => setShowHistory(!showHistory), className: `flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold transition-colors ${showHistory ? "bg-zinc-200 dark:bg-zinc-800 text-black dark:text-white" : "text-zinc-500 hover:text-black dark:hover:text-white"}`, children: [
228            /* @__PURE__ */ jsxRuntimeExports.jsx(History, { size: 14 }),
229            " History"
230          ] }) }),
231          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
232            /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleCopyForGemini, className: "flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold text-indigo-600 dark:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-indigo-900/20 transition-colors", children: [
233              copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { size: 14 }),
234              " ",
235              copied ? "Copied" : "Copy Prompt"
236            ] }),
237            /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => setShowUploadModal(true), className: "flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold bg-indigo-600 text-white hover:bg-indigo-700 transition-colors", children: [
238              /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { size: 14 }),
239              " Update"
240            ] })
241          ] })
242        ] }),
243        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden relative flex", children: showHistory ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 z-10 bg-zinc-50 dark:bg-zinc-900 p-6 overflow-y-auto", children: [
244          /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "font-bold text-lg mb-4 flex items-center gap-2 text-zinc-900 dark:text-white", children: [
245            /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 20 }),
246            " Version History"
247          ] }),
248          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 max-w-3xl", children: [
249            selectedFile.history.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-zinc-500 italic", children: "No edit history found." }),
250            selectedFile.history.map((ver, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-black border border-zinc-200 dark:border-zinc-800 rounded-lg p-4 flex justify-between items-start hover:shadow-md transition-shadow", children: [
251              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
252                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
253                  /* @__P
253URE__ */ jsxRuntimeExports.jsxs("span", { className: "font-bold text-zinc-900 dark:text-white", children: [
254                    "Version ",
255                    ver.version
256                  ] }),
257                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs bg-zinc-100 dark:bg-zinc-800 px-2 py-0.5 rounded text-zinc-500", children: ver.timestamp })
258                ] }),
259                /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-zinc-600 dark:text-zinc-400", children: [
260                  "By ",
261                  ver.author
262                ] }),
263                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-2 font-mono", children: ver.changeLog })
264              ] }),
265              /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => handleRestore(ver), className: "px-3 py-1.5 bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 rounded text-xs font-bold text-zinc-700 dark:text-zinc-300 flex items-center gap-1", children: [
266                /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }),
267                " Restore"
268              ] })
269            ] }, i))
270          ] })
271        ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("textarea", { value: isEditing ? editContent : selectedFile.content, onChange: (e) => setEditContent(e.target.value), readOnly: !isEditing, className: `w-full h-full p-4 font-mono text-xs outline-none resize-none ${isEditing ? "bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white" : "bg-zinc-50 dark:bg-black text-zinc-600 dark:text-zinc-400"}`, spellCheck: false }) })
272      ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center text-zinc-400 gap-4", children: [
273        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-16 h-16 bg-zinc-100 dark:bg-zinc-800 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 32, className: "text-zinc-300 dark:text-zinc-700" }) }),
274        /* @__P
274URE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "Select a file from the explorer to view or edit." })
275      ] }) })
276    ] }),
277    showUploadModal && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-[100] flex items-center justify-center p-4", children: [
278      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: () => setShowUploadModal(false) }),
279      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full max-w-3xl bg-white dark:bg-zinc-900 rounded-xl shadow-2xl flex flex-col h-[600px] animate-in zoom-in-95 border border-zinc-200 dark:border-zinc-800", children: [
280        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 border-b border-zinc-200 dark:border-zinc-800 flex justify-between items-center bg-zinc-50 dark:bg-zinc-950", children: [
281          /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "font-bold text-lg text-zinc-900 dark:text-white", children: [
282            "Update Code for ",
283            selectedFile == null ? void 0 : selectedFile.path
284          ] }),
285          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowUploadModal(false), children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "text-zinc-500" }) })
286        ] }),
287        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 p-4 flex flex-col", children: [
288          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-indigo-50 dark:bg-indigo-900/20 p-3 rounded-lg mb-4 text-xs text-indigo-800 dark:text-indigo-300", children: "Paste the updated code generated by Gemini below. This will create a new version in the history." }),
289          /* @__PURE__ */ jsxRuntimeExports.jsx("textarea", { value: newCodeInput, onChange: (e) => setNewCodeInput(e.target.value), className: "flex-1 bg-zinc-50 dark:bg-black border border-zinc-300 dark:border-zinc-700 rounded-lg p-4 font-mono text-xs outline-none focus:border-indigo-500 text-zinc-900 dark:text-white", placeholder: "// Paste updated code here..." })
290        ] }),
291        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 border-t border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-950 flex justify-end gap-3", children: [
292          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowUploadModal(false), className: "px-4 py-2 rounded-lg font-bold text-zinc-600 hover:bg-zinc-200 dark:text-zinc-400 dark:hover:bg-zinc-800", children: "Cancel" }),
293          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleApplyUpload, disabled: !newCodeInput, className: "px-4 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white font-bold disabled:opacity-50", children: "Apply Changes" })
294        ] })
295      ] })
296    ] }),
297    showCreateModal && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-[100] flex items-center justify-center p-4", children: [
298      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: () => setShowCreateModal(false) }),
299      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full max-w-md bg-white dark:bg-zinc-900 rounded-xl shadow-2xl animate-in zoom-in-95 border border-zinc-200 dark:border-zinc-800 p-6", children: [
300        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "font-bold text-lg text-zinc-900 dark:text-white mb-4", children: "Create New Module" }),
301        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
302          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
303            /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-bold text-zinc-500 uppercase", children: "Path" }),
304            /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "text", value: newFileFolder, onChange: (e) => setNewFileFolder(e.target.value), className: "w-full mt-1 p-2 rounded border dark:bg-zinc-950 dark:border-zinc-800 text-zinc-900 dark:text-white text-sm font-mono" })
305          ] }),
306          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
307            /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-bold text-zinc-500 uppercase", children: "Filename" }),
308            /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "text", value: newFileName, onChange: (e) => setNewFileName(e.target.value), placeholder: "MyNewModule.tsx", className: "w-full mt-1 p-2 rounded border dark:bg-zinc-950 dark:border-zinc-800 text-zinc-900 dark:text-white text-sm font-mono" })
309          ] }),
310          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
311            /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowCreateModal(false), className: "px-4 py-2 rounded-lg text-zinc-600 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800 font-bold text-sm", children: "Cancel" }),
312            /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleCreateFile, disabled: !newFileName, className: "px-4 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-sm", children: "Create" })
313          ] })
314        ] })
315      ] })
316    ] })
317  ] });
318};
319export {
320  FileExplorer as default
321};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.