drop down for code editor
This commit is contained in:
@@ -5,14 +5,14 @@ import { Route, Routes } from "react-router-dom";
|
|||||||
// import { Input } from "./components/input/Input";
|
// import { Input } from "./components/input/Input";
|
||||||
// import { Switch } from "./components/switch/Switch";
|
// import { Switch } from "./components/switch/Switch";
|
||||||
import Home from "./pages/Home";
|
import Home from "./pages/Home";
|
||||||
import CodeEditor from "./components/codeeditor/CodeEditor";
|
import CodeEditor from "./views/problem/codeeditor/CodeEditor";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full h-full ">
|
<div className="flex w-full h-full ">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/home/*" element={<Home/>}/>
|
<Route path="/home/*" element={<Home/>}/>
|
||||||
<Route path="/editor" element={<div className="box-border p-[50px] w-full h-[800px] relative bg-red-800"><CodeEditor/></div>}/>
|
<Route path="/editor" element={<div className="box-border p-[50px] w-full h-[800px] relative bg-red-8001"><CodeEditor/></div>}/>
|
||||||
<Route path="*" element={<Home/>}/>
|
<Route path="*" element={<Home/>}/>
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
||||||
|
|||||||
3
src/assets/icons/input/check-mark.svg
Normal file
3
src/assets/icons/input/check-mark.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="11" height="8" viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0.707031 3.70711L3.70787 6.70711L9.70703 0.707108" stroke="#EDF6F7" stroke-linecap="square" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 229 B |
3
src/assets/icons/input/chevron-drop-down.svg
Normal file
3
src/assets/icons/input/chevron-drop-down.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 10L12.0008 14.58L17 10" stroke="#EDF6F7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 222 B |
@@ -2,6 +2,7 @@ import eyeClosed from "./eye-closed.svg"
|
|||||||
import eyeOpen from "./eye-open.png"
|
import eyeOpen from "./eye-open.png"
|
||||||
import googleLogo from "./google-logo.svg"
|
import googleLogo from "./google-logo.svg"
|
||||||
import upload from "./upload.svg"
|
import upload from "./upload.svg"
|
||||||
|
import chevroneDropDownList from "./chevron-drop-down.svg"
|
||||||
|
import checkMark from "./check-mark.svg"
|
||||||
|
|
||||||
|
export {eyeClosed, eyeOpen, googleLogo, upload, chevroneDropDownList, checkMark}
|
||||||
export {eyeClosed, eyeOpen, googleLogo, upload}
|
|
||||||
@@ -1,78 +1,87 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { cn } from "../../lib/cn";
|
import { cn } from "../../lib/cn";
|
||||||
import { eyeClosed, eyeOpen } from "../../assets/icons/input";
|
import { checkMark, chevroneDropDownList } from "../../assets/icons/input";
|
||||||
|
|
||||||
interface DwopDownListProps {
|
export interface DropDownListItem{
|
||||||
name?: string;
|
text: string;
|
||||||
type: "text" | "email" | "password" | "first_name";
|
value: string;
|
||||||
error?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
required?: boolean;
|
|
||||||
label?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
className?: string;
|
|
||||||
onChange: (state: string) => void;
|
|
||||||
defaultState?: string;
|
|
||||||
autocomplete?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DwopDownList: React.FC<DwopDownListProps> = ({
|
interface DropDownListProps {
|
||||||
type = "text",
|
disabled?: boolean;
|
||||||
error = "",
|
className?: string;
|
||||||
// disabled = false,
|
onChange: (state: string) => void;
|
||||||
// required = false,
|
defaultState?: DropDownListItem;
|
||||||
label = "",
|
items: DropDownListItem[];
|
||||||
placeholder = "",
|
}
|
||||||
className = "",
|
|
||||||
onChange,
|
export const DropDownList: React.FC<DropDownListProps> = ({
|
||||||
defaultState = "",
|
// disabled = false,
|
||||||
name = "",
|
className = "",
|
||||||
autocomplete="",
|
onChange,
|
||||||
|
defaultState,
|
||||||
|
items = [{text: "", value: ""}],
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = React.useState<string>(defaultState);
|
if (items.length == 0)
|
||||||
const [visible, setVIsible] = React.useState<boolean>(type != "password");
|
items.push({text: "", value: ""});
|
||||||
|
|
||||||
React.useEffect(() => onChange(value), [value]);
|
const [value, setValue] = React.useState<DropDownListItem>(defaultState != undefined ? defaultState : items[0]);
|
||||||
|
const [active, setActive] = React.useState<boolean>(false);
|
||||||
|
|
||||||
|
React.useEffect(() => onChange(value.value), [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn(
|
||||||
|
"relative",
|
||||||
|
className
|
||||||
|
)}>
|
||||||
|
<div className={cn(" flex items-center h-[40px] rounded-[10px] bg-liquid-lighter px-[16px] w-[180px]",
|
||||||
|
"text-[18px] font-bold cursor-pointer select-none",
|
||||||
|
"transitin-all active:scale-95 duration-300"
|
||||||
|
)}
|
||||||
|
onClick={() => setActive(!active)}>
|
||||||
|
{value.text}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img src={chevroneDropDownList}
|
||||||
|
className={cn(" absolute right-[16px] h-[24px] w-[24px] top-[8.5px] rotate-0 transition-all duration-300 pointer-events-none",
|
||||||
|
active && " rotate-180"
|
||||||
|
)}/>
|
||||||
|
|
||||||
|
|
||||||
return (
|
<div className={cn(" absolute rounded-[10px] bg-liquid-lighter w-[180px] left-0 top-[48px] z-50 transition-all duration-300",
|
||||||
<div className={cn(
|
"grid overflow-hidden",
|
||||||
"relative",
|
active ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0",
|
||||||
className
|
)}>
|
||||||
)}>
|
<div className=" overflow-hidden p-[8px]">
|
||||||
<div className={cn("text-[18px] text-liquid-white font-medium h-[23px] mb-[10px] transition-all",
|
<div className={cn(
|
||||||
label == "" && "h-0 mb-0"
|
" overflow-y-scroll max-h-[200px] thin-scrollbar pr-[8px]",
|
||||||
)}>
|
)}>
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
<div className="relative">
|
|
||||||
<input
|
|
||||||
className={cn(
|
|
||||||
"bg-liquid-lighter w-full rounded-[10px] outline-none pl-[16px] py-[8px] placeholder:text-liquid-light",
|
|
||||||
type == "password" ? "h-[40px]" : "h-[36px]"
|
|
||||||
)}
|
|
||||||
name={name}
|
|
||||||
autoComplete={autocomplete}
|
|
||||||
type={type == "password" ? (visible ? "text" : "password") : type}
|
|
||||||
placeholder={placeholder}
|
|
||||||
onChange={(e) => {
|
|
||||||
setValue(e.target.value);
|
|
||||||
}} />
|
|
||||||
{
|
|
||||||
type == "password" &&
|
|
||||||
<img src={visible ? eyeOpen : eyeClosed} className="w-[24px] h-[24px] cursor-pointer right-[16px] top-[8px] absolute" onClick={() => {
|
|
||||||
setVIsible(!visible);
|
|
||||||
}}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={cn("text-liquid-red text-[14px] h-[18px] text-right mt-[5px]",
|
{items.map((v, i) =>
|
||||||
error == "" && "h-0 mt-0"
|
<div
|
||||||
)}>
|
key={i}
|
||||||
{error}
|
className={cn(
|
||||||
</div>
|
"cursor-pointer h-[36px] relative",
|
||||||
|
i + 1 != items.length && "border-b-liquid-light border-b-[1px]",
|
||||||
|
"text-[16px] font-medium cursor-pointer select-none flex items-center pl-[8px]",
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
setValue(v);
|
||||||
|
setActive(false);
|
||||||
|
}}>
|
||||||
|
{v.text}
|
||||||
|
|
||||||
</div>
|
{v.text == value.text &&
|
||||||
);
|
<img src={checkMark} className=" absolute right-[8px]"/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,3 +35,24 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Общий контейнер полосы прокрутки */
|
||||||
|
.thin-scrollbar::-webkit-scrollbar {
|
||||||
|
width: 4px; /* ширина вертикального */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Трек (фон) */
|
||||||
|
.thin-scrollbar::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ползунок (thumb) */
|
||||||
|
.thin-scrollbar::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--color-liquid-light);
|
||||||
|
border-radius: 1000px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Editor from "@monaco-editor/react";
|
import Editor from "@monaco-editor/react";
|
||||||
import { upload } from "../../assets/icons/input";
|
import { upload } from "../../../assets/icons/input";
|
||||||
import { cn } from "../../lib/cn";
|
import { cn } from "../../../lib/cn";
|
||||||
|
import { DropDownList } from "../../../components/drop-down-list/DropDownList";
|
||||||
|
|
||||||
const languageMap: Record<string, string> = {
|
const languageMap: Record<string, string> = {
|
||||||
c: "cpp",
|
c: "cpp",
|
||||||
@@ -16,6 +17,15 @@ const CodeEditor: React.FC = () => {
|
|||||||
const [code, setCode] = useState<string>("");
|
const [code, setCode] = useState<string>("");
|
||||||
const [isDragging, setIsDragging] = useState<boolean>(false);
|
const [isDragging, setIsDragging] = useState<boolean>(false);
|
||||||
|
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ value: "c", text: "C" },
|
||||||
|
{ value: "cpp", text: "C++" },
|
||||||
|
{ value: "java", text: "Java" },
|
||||||
|
{ value: "python", text: "Python" },
|
||||||
|
{ value: "pascal", text: "Pascal" },
|
||||||
|
];
|
||||||
|
|
||||||
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
@@ -62,17 +72,7 @@ const CodeEditor: React.FC = () => {
|
|||||||
{/* Панель выбора языка и загрузки файла */}
|
{/* Панель выбора языка и загрузки файла */}
|
||||||
<div className="flex items-center justify-between p-3 ">
|
<div className="flex items-center justify-between p-3 ">
|
||||||
<div className="flex items-center gap-[20px]">
|
<div className="flex items-center gap-[20px]">
|
||||||
<select
|
<DropDownList items={items} onChange={(v) => { setLanguage(v) }} />
|
||||||
value={language}
|
|
||||||
onChange={(e) => setLanguage(e.target.value)}
|
|
||||||
className=" rounded-md px-3 py-1"
|
|
||||||
>
|
|
||||||
<option value="c">C</option>
|
|
||||||
<option value="cpp">C++</option>
|
|
||||||
<option value="java">Java</option>
|
|
||||||
<option value="python">Python</option>
|
|
||||||
<option value="pascal">Pascal</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className={cn("h-[40px] w-[250px] rounded-[10px] px-[16px] relative flex items-center cursor-pointer transition-all bg-liquid-lighter outline-dashed outline-[2px] outline-transparent active:scale-[95%]",
|
className={cn("h-[40px] w-[250px] rounded-[10px] px-[16px] relative flex items-center cursor-pointer transition-all bg-liquid-lighter outline-dashed outline-[2px] outline-transparent active:scale-[95%]",
|
||||||
Reference in New Issue
Block a user