This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { MdAdd } from "react-icons/md";
|
import { MdAdd, MdArrowBack } from "react-icons/md";
|
||||||
import { GoTrash } from "react-icons/go";
|
import { GoTrash } from "react-icons/go";
|
||||||
import {
|
import {
|
||||||
useIDEStore,
|
useIDEStore,
|
||||||
@@ -16,10 +16,12 @@ import {
|
|||||||
|
|
||||||
interface IDEProps {
|
interface IDEProps {
|
||||||
initialFiles?: FileNode;
|
initialFiles?: FileNode;
|
||||||
|
onBack?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IDE: React.FC<IDEProps> = ({
|
export const IDE: React.FC<IDEProps> = ({
|
||||||
initialFiles: externalFiles,
|
initialFiles: externalFiles,
|
||||||
|
onBack,
|
||||||
}: IDEProps = {}) => {
|
}: IDEProps = {}) => {
|
||||||
const files = useIDEStore((state) => state.files);
|
const files = useIDEStore((state) => state.files);
|
||||||
const openFiles = useIDEStore((state) => state.openFiles);
|
const openFiles = useIDEStore((state) => state.openFiles);
|
||||||
@@ -52,9 +54,46 @@ export const IDE: React.FC<IDEProps> = ({
|
|||||||
backgroundColor: "#1e1e1e",
|
backgroundColor: "#1e1e1e",
|
||||||
fontFamily:
|
fontFamily:
|
||||||
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
||||||
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TitleBar />
|
<TitleBar />
|
||||||
|
{onBack && (
|
||||||
|
<button
|
||||||
|
onClick={onBack}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "40px",
|
||||||
|
left: "12px",
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid #3e3e42",
|
||||||
|
color: "#cccccc",
|
||||||
|
cursor: "pointer",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "6px",
|
||||||
|
padding: "6px 12px",
|
||||||
|
borderRadius: "6px",
|
||||||
|
fontSize: "12px",
|
||||||
|
transition: "all 0.1s",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.backgroundColor = "#3e3e42";
|
||||||
|
e.currentTarget.style.color = "#fff";
|
||||||
|
e.currentTarget.style.borderColor = "#555";
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.backgroundColor = "transparent";
|
||||||
|
e.currentTarget.style.color = "#cccccc";
|
||||||
|
e.currentTarget.style.borderColor = "#3e3e42";
|
||||||
|
}}
|
||||||
|
title="Go back"
|
||||||
|
>
|
||||||
|
<MdArrowBack size={16} />
|
||||||
|
<span>Back</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -140,7 +179,8 @@ export const IDE: React.FC<IDEProps> = ({
|
|||||||
backgroundColor: "#323233",
|
backgroundColor: "#323233",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "space-between",
|
||||||
|
padding: "0 8px",
|
||||||
borderBottom: "1px solid #1e1e1e",
|
borderBottom: "1px solid #1e1e1e",
|
||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
color: "#cccccc",
|
color: "#cccccc",
|
||||||
@@ -148,10 +188,42 @@ export const IDE: React.FC<IDEProps> = ({
|
|||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{onBack && (
|
||||||
|
<button
|
||||||
|
onClick={onBack}
|
||||||
|
style={{
|
||||||
|
background: "transparent",
|
||||||
|
border: "none",
|
||||||
|
color: "#cccccc",
|
||||||
|
cursor: "pointer",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "4px",
|
||||||
|
padding: "4px 8px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
fontSize: "11px",
|
||||||
|
transition: "all 0.1s",
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.backgroundColor = "#3e3e42";
|
||||||
|
e.currentTarget.style.color = "#fff";
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.backgroundColor = "transparent";
|
||||||
|
e.currentTarget.style.color = "#cccccc";
|
||||||
|
}}
|
||||||
|
title="Go back"
|
||||||
|
>
|
||||||
|
<MdArrowBack size={14} />
|
||||||
|
<span>Back</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{!onBack && <div />}
|
||||||
<span style={{ fontWeight: 400 }}>
|
<span style={{ fontWeight: 400 }}>
|
||||||
{activeFile ? `${activeFile.name} - ` : ""}
|
{activeFile ? `${activeFile.name} - ` : ""}
|
||||||
{files.name}
|
{files.name}
|
||||||
</span>
|
</span>
|
||||||
|
<div style={{ width: 60 }} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", flex: 1, overflow: "hidden" }}>
|
<div style={{ display: "flex", flex: 1, overflow: "hidden" }}>
|
||||||
<div style={{ width: "260px", flexShrink: 0 }}>
|
<div style={{ width: "260px", flexShrink: 0 }}>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState, useRef, useCallback } from "react";
|
||||||
import { FiSearch, FiFile, FiFolder, FiMinus } from "react-icons/fi";
|
import { FiSearch, FiFile, FiFolder, FiMinus } from "react-icons/fi";
|
||||||
import { GoKebabHorizontal } from "react-icons/go";
|
import { GoKebabHorizontal } from "react-icons/go";
|
||||||
import { MdClose, MdAdd } from "react-icons/md";
|
import { MdClose, MdAdd } from "react-icons/md";
|
||||||
@@ -20,6 +20,28 @@ export const FileExplorer: React.FC<FileExplorerProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const store = useIDEStore();
|
const store = useIDEStore();
|
||||||
const [showSearch, setShowSearch] = useState(false);
|
const [showSearch, setShowSearch] = useState(false);
|
||||||
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
// Фокус на инпут при открытии поиска
|
||||||
|
useEffect(() => {
|
||||||
|
if (showSearch) {
|
||||||
|
searchInputRef.current?.focus();
|
||||||
|
}
|
||||||
|
}, [showSearch]);
|
||||||
|
|
||||||
|
const handleSearchBlur = useCallback(() => {
|
||||||
|
// Скрываем поиск при потере фокуса с небольшой задержкой,
|
||||||
|
// чтобы клики по кнопке очистки успели сработать
|
||||||
|
setTimeout(() => {
|
||||||
|
if (
|
||||||
|
searchInputRef.current &&
|
||||||
|
!searchInputRef.current.contains(document.activeElement)
|
||||||
|
) {
|
||||||
|
setShowSearch(false);
|
||||||
|
store.setSearchQuery("");
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}, [store]);
|
||||||
|
|
||||||
const handleEmptyContextMenu = (e: React.MouseEvent) => {
|
const handleEmptyContextMenu = (e: React.MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -78,7 +100,14 @@ export const FileExplorer: React.FC<FileExplorerProps> = ({
|
|||||||
</span>
|
</span>
|
||||||
<div style={{ display: "flex", gap: "2px", alignItems: "center" }}>
|
<div style={{ display: "flex", gap: "2px", alignItems: "center" }}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowSearch(!showSearch)}
|
onClick={() => {
|
||||||
|
if (!showSearch) {
|
||||||
|
setShowSearch(true);
|
||||||
|
} else {
|
||||||
|
setShowSearch(false);
|
||||||
|
store.setSearchQuery("");
|
||||||
|
}
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: "transparent",
|
background: "transparent",
|
||||||
border: "none",
|
border: "none",
|
||||||
@@ -196,11 +225,12 @@ export const FileExplorer: React.FC<FileExplorerProps> = ({
|
|||||||
>
|
>
|
||||||
<FiSearch size={13} color="#858585" />
|
<FiSearch size={13} color="#858585" />
|
||||||
<input
|
<input
|
||||||
|
ref={searchInputRef}
|
||||||
type="text"
|
type="text"
|
||||||
value={store.searchQuery}
|
value={store.searchQuery}
|
||||||
onChange={(e) => store.setSearchQuery(e.target.value)}
|
onChange={(e) => store.setSearchQuery(e.target.value)}
|
||||||
|
onBlur={handleSearchBlur}
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
autoFocus
|
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
padding: "5px 6px",
|
padding: "5px 6px",
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import { IDE } from "../modules/ide";
|
import { IDE } from "../modules/ide";
|
||||||
|
|
||||||
export const IDEPage = () => {
|
export const IDEPage = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
return (
|
return (
|
||||||
<div className="absolute top-0 left-0 w-full h-full z-90">
|
<div className="absolute top-0 left-0 w-full h-full z-90">
|
||||||
<IDE initialFiles={{ name: "тест", type: "folder" }} />
|
<IDE
|
||||||
|
onBack={() => navigate("/home")}
|
||||||
|
initialFiles={{ name: "тест", type: "folder" }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user