Add editor lang

This commit is contained in:
Виталий Лавшонок
2025-10-27 13:24:01 +03:00
parent 8fa48ef67e
commit 1690169d5a
6 changed files with 59 additions and 21 deletions

View File

@@ -12,7 +12,7 @@ function App() {
<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-8001"><CodeEditor/></div>}/> <Route path="/editor" element={<div className="box-border p-[50px] w-full h-[800px] relative bg-red-800"><CodeEditor/></div>}/>
<Route path="*" element={<Home/>}/> <Route path="*" element={<Home/>}/>
</Routes> </Routes>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -1,15 +1,16 @@
import React from "react"; import React from "react";
import { cn } from "../../lib/cn"; import { cn } from "../../lib/cn";
import { checkMark, chevroneDropDownList } from "../../assets/icons/input"; import { checkMark, chevroneDropDownList } from "../../assets/icons/input";
import { useClickOutside } from "../../hooks/useClickOutside";
export interface DropDownListItem{ export interface DropDownListItem {
text: string; text: string;
value: string; value: string;
} }
interface DropDownListProps { interface DropDownListProps {
disabled?: boolean; disabled?: boolean;
className?: string; className?: string;
onChange: (state: string) => void; onChange: (state: string) => void;
defaultState?: DropDownListItem; defaultState?: DropDownListItem;
items: DropDownListItem[]; items: DropDownListItem[];
@@ -20,52 +21,67 @@ export const DropDownList: React.FC<DropDownListProps> = ({
className = "", className = "",
onChange, onChange,
defaultState, defaultState,
items = [{text: "", value: ""}], items = [{ text: "", value: "" }],
}) => { }) => {
if (items.length == 0) if (items.length == 0)
items.push({text: "", value: ""}); items.push({ text: "", value: "" });
const [value, setValue] = React.useState<DropDownListItem>(defaultState != undefined ? defaultState : items[0]); const [value, setValue] = React.useState<DropDownListItem>(defaultState != undefined ? defaultState : items[0]);
const [active, setActive] = React.useState<boolean>(false); const [active, setActive] = React.useState<boolean>(false);
React.useEffect(() => onChange(value.value), [value]); React.useEffect(() => onChange(value.value), [value]);
const ref = React.useRef<HTMLDivElement>(null);
useClickOutside(ref, () => {
setActive(false);
});
return ( return (
<div className={cn( <div className={cn(
"relative", "relative",
className className
)}> )}
ref={ref}
>
<div className={cn(" flex items-center h-[40px] rounded-[10px] bg-liquid-lighter px-[16px] w-[180px]", <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", "text-[18px] font-bold cursor-pointer select-none",
"transitin-all active:scale-95 duration-300" "transitin-all active:scale-95 duration-300"
)} )}
onClick={() => setActive(!active)}> onClick={() => {
setActive(!active);
}
}>
{value.text} {value.text}
</div> </div>
<img src={chevroneDropDownList} <img src={chevroneDropDownList}
className={cn(" absolute right-[16px] h-[24px] w-[24px] top-[8.5px] rotate-0 transition-all duration-300 pointer-events-none", className={cn(" absolute right-[16px] h-[24px] w-[24px] top-[8.5px] rotate-0 transition-all duration-300 pointer-events-none",
active && " rotate-180" active && " rotate-180"
)}/> )} />
<div className={cn(" absolute rounded-[10px] bg-liquid-lighter w-[180px] left-0 top-[48px] z-50 transition-all duration-300", <div
"grid overflow-hidden", className={cn(" absolute rounded-[10px] bg-liquid-lighter w-[180px] left-0 top-[48px] z-50 transition-all duration-300",
active ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0", "grid overflow-hidden",
)}> active ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0",
)}>
<div className=" overflow-hidden p-[8px]"> <div className=" overflow-hidden p-[8px]">
<div className={cn( <div className={cn(
" overflow-y-scroll max-h-[200px] thin-scrollbar pr-[8px]", " overflow-y-scroll max-h-[200px] thin-scrollbar pr-[8px] ",
)}> )}>
{items.map((v, i) => {items.map((v, i) =>
<div <div
key={i} key={i}
className={cn( className={cn(
"cursor-pointer h-[36px] relative", "cursor-pointer h-[36px] relative transition-all duration-300",
i + 1 != items.length && "border-b-liquid-light border-b-[1px]", i + 1 != items.length && "border-b-liquid-light border-b-[1px]",
"text-[16px] font-medium cursor-pointer select-none flex items-center pl-[8px]", "text-[16px] font-medium cursor-pointer select-none flex items-center pl-[8px]",
"hover:bg-liquid-background",
"first:rounded-t-[6px] last:rounded-b-[6px]"
)} )}
onClick={() => { onClick={() => {
setValue(v); setValue(v);
@@ -73,8 +89,8 @@ export const DropDownList: React.FC<DropDownListProps> = ({
}}> }}>
{v.text} {v.text}
{v.text == value.text && {v.text == value.text &&
<img src={checkMark} className=" absolute right-[8px]"/> <img src={checkMark} className=" absolute right-[8px]" />
} }
</div> </div>
)} )}

View File

@@ -0,0 +1,18 @@
import React from "react";
export const useClickOutside = (ref: React.RefObject<any>, onClickOutside: () => void) => {
React.useEffect(() => {
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
if (ref.current && !ref.current.contains(event.target)) {
onClickOutside();
}
}
document.addEventListener("mousedown", handleClickOutside);
document.addEventListener("touchstart", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
document.removeEventListener("touchstart", handleClickOutside);
}
}, [ref, onClickOutside]);
}

View File

@@ -10,6 +10,8 @@ const languageMap: Record<string, string> = {
java: "java", java: "java",
python: "python", python: "python",
pascal: "pascal", pascal: "pascal",
kotlin: "kotlin",
csharp: "csharp"
}; };
const CodeEditor: React.FC = () => { const CodeEditor: React.FC = () => {
@@ -22,8 +24,10 @@ const CodeEditor: React.FC = () => {
{ value: "c", text: "C" }, { value: "c", text: "C" },
{ value: "cpp", text: "C++" }, { value: "cpp", text: "C++" },
{ value: "java", text: "Java" }, { value: "java", text: "Java" },
{ value: "python", text: "Python" }, { value: "python", text: "Python" },
{ value: "pascal", text: "Pascal" }, { value: "pascal", text: "Pascal" },
{ value: "kotlin", text: "Kotlin" },
{ value: "csharp", text: "C#" },
]; ];
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => { const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -70,7 +74,7 @@ const CodeEditor: React.FC = () => {
return ( return (
<div className="flex flex-col w-full h-full"> <div className="flex flex-col w-full h-full">
{/* Панель выбора языка и загрузки файла */} {/* Панель выбора языка и загрузки файла */}
<div className="flex items-center justify-between p-3 "> <div className="flex items-center justify-between py-3 ">
<div className="flex items-center gap-[20px]"> <div className="flex items-center gap-[20px]">
<DropDownList items={items} onChange={(v) => { setLanguage(v) }} /> <DropDownList items={items} onChange={(v) => { setLanguage(v) }} />