diff --git a/package-lock.json b/package-lock.json
index 8b747af..799d483 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,11 +8,13 @@
"name": "react-kit",
"version": "0.0.0",
"dependencies": {
+ "@monaco-editor/react": "^4.7.0",
"@reduxjs/toolkit": "^2.9.2",
"@types/react-redux": "^7.1.33",
"axios": "^1.12.2",
"clsx": "^2.1.1",
"framer-motion": "^11.9.0",
+ "monaco-editor": "^0.54.0",
"postcss": "^8.4.47",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -1022,6 +1024,29 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@monaco-editor/loader": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.6.1.tgz",
+ "integrity": "sha512-w3tEnj9HYEC73wtjdpR089AqkUPskFRcdkxsiSFt3SoUc3OHpmu+leP94CXBm4mHfefmhsdfI0ZQu6qJ0wgtPg==",
+ "license": "MIT",
+ "dependencies": {
+ "state-local": "^1.0.6"
+ }
+ },
+ "node_modules/@monaco-editor/react": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
+ "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.5.0"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.25.0 < 1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2181,6 +2206,12 @@
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"license": "MIT"
},
+ "node_modules/dompurify": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
+ "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==",
+ "license": "(MPL-2.0 OR Apache-2.0)"
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -3315,6 +3346,18 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/marked": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
+ "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -3389,6 +3432,16 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/monaco-editor": {
+ "version": "0.54.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.54.0.tgz",
+ "integrity": "sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==",
+ "license": "MIT",
+ "dependencies": {
+ "dompurify": "3.1.7",
+ "marked": "14.0.0"
+ }
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -4142,6 +4195,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
+ "license": "MIT"
+ },
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
diff --git a/package.json b/package.json
index df92240..33cd567 100644
--- a/package.json
+++ b/package.json
@@ -10,11 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
+ "@monaco-editor/react": "^4.7.0",
"@reduxjs/toolkit": "^2.9.2",
"@types/react-redux": "^7.1.33",
"axios": "^1.12.2",
"clsx": "^2.1.1",
"framer-motion": "^11.9.0",
+ "monaco-editor": "^0.54.0",
"postcss": "^8.4.47",
"react": "^18.3.1",
"react-dom": "^18.3.1",
diff --git a/src/App.tsx b/src/App.tsx
index 65240b0..d02b174 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,12 +5,14 @@ import { Route, Routes } from "react-router-dom";
// import { Input } from "./components/input/Input";
// import { Switch } from "./components/switch/Switch";
import Home from "./pages/Home";
+import CodeEditor from "./components/codeeditor/CodeEditor";
function App() {
return (
-
+
}/>
+
}/>
}/>
diff --git a/src/assets/icons/input/index.ts b/src/assets/icons/input/index.ts
index d8a755a..b9f6e60 100644
--- a/src/assets/icons/input/index.ts
+++ b/src/assets/icons/input/index.ts
@@ -1,5 +1,7 @@
import eyeClosed from "./eye-closed.svg"
import eyeOpen from "./eye-open.png"
import googleLogo from "./google-logo.svg"
+import upload from "./upload.svg"
-export {eyeClosed, eyeOpen, googleLogo}
\ No newline at end of file
+
+export {eyeClosed, eyeOpen, googleLogo, upload}
\ No newline at end of file
diff --git a/src/assets/icons/input/upload.svg b/src/assets/icons/input/upload.svg
new file mode 100644
index 0000000..86f59a5
--- /dev/null
+++ b/src/assets/icons/input/upload.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/codeeditor/CodeEditor.tsx b/src/components/codeeditor/CodeEditor.tsx
new file mode 100644
index 0000000..2987a40
--- /dev/null
+++ b/src/components/codeeditor/CodeEditor.tsx
@@ -0,0 +1,125 @@
+import React, { useState } from "react";
+import Editor from "@monaco-editor/react";
+import { upload } from "../../assets/icons/input";
+import { cn } from "../../lib/cn";
+
+const languageMap: Record = {
+ c: "cpp",
+ cpp: "cpp",
+ java: "java",
+ python: "python",
+ pascal: "pascal",
+};
+
+const CodeEditor: React.FC = () => {
+ const [language, setLanguage] = useState("cpp");
+ const [code, setCode] = useState("");
+ const [isDragging, setIsDragging] = useState(false);
+
+ const handleFileUpload = (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0];
+ if (!file) return;
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const text = event.target?.result;
+ if (typeof text === "string") setCode(text);
+ };
+ reader.readAsText(file);
+ e.target.value = "";
+ };
+
+ const handleDrop = (e: React.DragEvent) => {
+ e.preventDefault();
+ setIsDragging(false);
+ const droppedFile = e.dataTransfer.files[0];
+ if (!droppedFile) return;
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const text = event.target?.result;
+ if (typeof text === "string") setCode(text);
+ };
+ reader.readAsText(droppedFile);
+ };
+
+ const handleDragOver = (e: React.DragEvent) => {
+ e.preventDefault(); // обязательно
+ };
+
+ const handleDragEnter = (e: React.DragEvent) => {
+ e.preventDefault();
+ setIsDragging(true);
+ };
+
+ const handleDragLeave = (e: React.DragEvent) => {
+ e.preventDefault();
+ setIsDragging(false);
+ };
+
+ return (
+
+ {/* Панель выбора языка и загрузки файла */}
+
+
+
+
+
+
+
+
+ {/* Monaco Editor */}
+
+ setCode(value ?? "")}
+ theme="vs-dark"
+ options={{
+ fontSize: 14,
+ minimap: { enabled: false },
+ automaticLayout: true,
+ quickSuggestions: true,
+ suggestOnTriggerCharacters: true,
+ tabSize: 4,
+ insertSpaces: true,
+ detectIndentation: false,
+ autoIndent: "full",
+ }}
+ />
+
+
+ );
+};
+
+export default CodeEditor;
diff --git a/src/components/drop-down-list/DropDownList.tsx b/src/components/drop-down-list/DropDownList.tsx
new file mode 100644
index 0000000..e70ccfa
--- /dev/null
+++ b/src/components/drop-down-list/DropDownList.tsx
@@ -0,0 +1,78 @@
+import React from "react";
+import { cn } from "../../lib/cn";
+import { eyeClosed, eyeOpen } from "../../assets/icons/input";
+
+interface DwopDownListProps {
+ name?: string;
+ type: "text" | "email" | "password" | "first_name";
+ 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 = ({
+ type = "text",
+ error = "",
+// disabled = false,
+// required = false,
+ label = "",
+ placeholder = "",
+ className = "",
+ onChange,
+ defaultState = "",
+ name = "",
+ autocomplete="",
+}) => {
+ const [value, setValue] = React.useState(defaultState);
+ const [visible, setVIsible] = React.useState(type != "password");
+
+ React.useEffect(() => onChange(value), [value]);
+
+
+ return (
+
+
+ {label}
+
+
+
{
+ setValue(e.target.value);
+ }} />
+ {
+ type == "password" &&
+

{
+ setVIsible(!visible);
+ }}/>
+ }
+
+
+
+ {error}
+
+
+
+ );
+
+};
diff --git a/src/components/input/Input.tsx b/src/components/input/Input.tsx
index 114a5f0..1b441f0 100644
--- a/src/components/input/Input.tsx
+++ b/src/components/input/Input.tsx
@@ -19,8 +19,8 @@ interface inputProps {
export const Input: React.FC = ({
type = "text",
error = "",
- disabled = false,
- required = false,
+ // disabled = false,
+ // required = false,
label = "",
placeholder = "",
className = "",