online-compiler-widget 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FileStorage/obj/FileStorage.csproj.EntityFrameworkCore.targets +28 -0
- package/README.md +1 -0
- package/eslint.config.js +26 -0
- package/index.html +13 -0
- package/openapitools.json +7 -0
- package/package.json +36 -0
- package/pnpm-workspace.yaml +2 -0
- package/public/vite.svg +1 -0
- package/src/App.css +49 -0
- package/src/App.tsx +84 -0
- package/src/api/.openapi-generator/FILES +25 -0
- package/src/api/.openapi-generator/VERSION +1 -0
- package/src/api/.openapi-generator-ignore +23 -0
- package/src/api/api.ts +1312 -0
- package/src/api/base.ts +62 -0
- package/src/api/common.ts +113 -0
- package/src/api/configuration.ts +121 -0
- package/src/api/docs/CompilationError.md +26 -0
- package/src/api/docs/CompileRequest.md +22 -0
- package/src/api/docs/CompileResult.md +28 -0
- package/src/api/docs/CompilerApi.md +263 -0
- package/src/api/docs/CreateFileDto.md +22 -0
- package/src/api/docs/CreateProjectRequest.md +20 -0
- package/src/api/docs/FileApi.md +274 -0
- package/src/api/docs/ProcessStatus.md +28 -0
- package/src/api/docs/ProjectApi.md +362 -0
- package/src/api/docs/ProjectInfo.md +24 -0
- package/src/api/docs/ProjectStats.md +28 -0
- package/src/api/docs/RenameFileDto.md +20 -0
- package/src/api/docs/RenameProjectRequest.md +20 -0
- package/src/api/docs/RunRequest.md +24 -0
- package/src/api/docs/RunResult.md +30 -0
- package/src/api/docs/RunningProjectInfo.md +26 -0
- package/src/api/docs/UpdateFileDto.md +20 -0
- package/src/api/git_push.sh +57 -0
- package/src/api/index.ts +18 -0
- package/src/assets/Badge.svg +17 -0
- package/src/assets/closeIcon.svg +20 -0
- package/src/assets/documentIcon.svg +11 -0
- package/src/assets/history.svg +11 -0
- package/src/assets/output.svg +12 -0
- package/src/assets/plus.svg +20 -0
- package/src/assets/react.svg +1 -0
- package/src/assets/save-icon.svg +11 -0
- package/src/assets/shield.svg +10 -0
- package/src/assets/start.svg +11 -0
- package/src/assets/stop.svg +11 -0
- package/src/components/CompilerWidget.module.scss +169 -0
- package/src/components/CompilerWidget.tsx +279 -0
- package/src/components/FileExplorer.module.scss +372 -0
- package/src/components/FileExplorer.tsx +285 -0
- package/src/components/MonacoEditorWrapper.module.scss +29 -0
- package/src/components/MonacoEditorWrapper.tsx +74 -0
- package/src/components/OutputPanel.module.scss +123 -0
- package/src/components/OutputPanel.tsx +53 -0
- package/src/components/RunContainer.module.scss +150 -0
- package/src/components/RunContainer.tsx +34 -0
- package/src/hooks/useCompiler.ts +228 -0
- package/src/hooks/useInitialNodes.ts +0 -0
- package/src/index.css +78 -0
- package/src/main.tsx +7 -0
- package/src/types/EditorDocument.ts +8 -0
- package/swagger.json +1020 -0
- package/tsconfig.app.json +29 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +8 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
button {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.runContainer {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
padding: 6px 7px;
|
|
10
|
+
border-top: 2px solid #E2E8F0;
|
|
11
|
+
background-color: #F8FAFC;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
.runText {
|
|
16
|
+
font-family: Arial;
|
|
17
|
+
font-weight: 400;
|
|
18
|
+
font-size: 12px;
|
|
19
|
+
padding: 0;
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.runButton {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: row;
|
|
26
|
+
width: auto;
|
|
27
|
+
padding: 6px 7px;
|
|
28
|
+
margin-right: 6px;
|
|
29
|
+
background-color: #74c56f;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.stopButton {
|
|
35
|
+
width: auto;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
flex-direction: row;
|
|
40
|
+
padding: 6px 7px;
|
|
41
|
+
background-color: #e57575;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.startIcon {
|
|
45
|
+
margin-right: 3px;
|
|
46
|
+
height: 11px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.stopIcon {
|
|
50
|
+
margin-right: 3px;
|
|
51
|
+
height: 13px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.baseButton {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: row;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
|
|
60
|
+
border: none;
|
|
61
|
+
border-radius: 6px;
|
|
62
|
+
padding: 6px 14px;
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
font-weight: 500;
|
|
65
|
+
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
transition: background 0.2s ease, transform 0.1s ease;
|
|
68
|
+
|
|
69
|
+
color: white; /* <-- иконкам цвет идёт отсюда */
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.baseButton:active {
|
|
73
|
+
transform: scale(0.97);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ===================== */
|
|
77
|
+
/* RUN BUTTON */
|
|
78
|
+
/* ===================== */
|
|
79
|
+
.runButton {
|
|
80
|
+
@extend .baseButton;
|
|
81
|
+
|
|
82
|
+
background: #22c55e;
|
|
83
|
+
|
|
84
|
+
&:hover {
|
|
85
|
+
background: #16a34a;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:active {
|
|
89
|
+
background: #15803d;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.startIcon {
|
|
94
|
+
width: 15px;
|
|
95
|
+
height: 15px;
|
|
96
|
+
margin-right: 6px;
|
|
97
|
+
color: white; /* SVG окрашивается */
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ===================== */
|
|
101
|
+
/* STOP BUTTON */
|
|
102
|
+
/* ===================== */
|
|
103
|
+
.stopButton {
|
|
104
|
+
@extend .baseButton;
|
|
105
|
+
margin-right: 5px;
|
|
106
|
+
|
|
107
|
+
background: #ef4444;
|
|
108
|
+
|
|
109
|
+
&:hover {
|
|
110
|
+
background: #dc2626;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:active {
|
|
114
|
+
background: #b91c1c;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.stopIcon {
|
|
119
|
+
width: 18px;
|
|
120
|
+
height: 18px;
|
|
121
|
+
margin-right: 6px;
|
|
122
|
+
color: white; // окрашивает stroke="currentColor"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* ===================== */
|
|
126
|
+
/* SAVE BUTTON */
|
|
127
|
+
/* ===================== */
|
|
128
|
+
.saveButton {
|
|
129
|
+
@extend .baseButton;
|
|
130
|
+
|
|
131
|
+
margin-left: auto;
|
|
132
|
+
margin-right: 7px;
|
|
133
|
+
|
|
134
|
+
background: #3b82f6;
|
|
135
|
+
|
|
136
|
+
&:hover {
|
|
137
|
+
background: #2563eb;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&:active {
|
|
141
|
+
background: #1d4ed8;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.saveIcon {
|
|
146
|
+
width: 16px;
|
|
147
|
+
height: 16px;
|
|
148
|
+
margin-right: 6px;
|
|
149
|
+
color: white; /* <-- ТЕПЕРЬ РАБОТАЕТ */
|
|
150
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/components/RunContainer.tsx
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import cls from './RunContainer.module.scss';
|
|
4
|
+
|
|
5
|
+
import StartIcon from "../assets/start.svg?react";
|
|
6
|
+
import StopIcon from "../assets/stop.svg?react";
|
|
7
|
+
import SaveIcon from "../assets/save-icon.svg?react"
|
|
8
|
+
import type {EditorDocument} from "../types/EditorDocument.ts";
|
|
9
|
+
import type {UpdateFileDto} from "../api";
|
|
10
|
+
|
|
11
|
+
interface RunContainerProps {
|
|
12
|
+
run: () => void,
|
|
13
|
+
stop: () => void,
|
|
14
|
+
save: () => void,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const RunContainer: React.FC<RunContainerProps> = (props: RunContainerProps) => {
|
|
18
|
+
return (
|
|
19
|
+
<div className={cls.runContainer}>
|
|
20
|
+
<button className={cls.runButton} onClick={props.run}>
|
|
21
|
+
<StartIcon className={cls.startIcon}/>
|
|
22
|
+
<p className={cls.runText}>Run</p>
|
|
23
|
+
</button>
|
|
24
|
+
<button className={cls.stopButton} onClick={props.stop}>
|
|
25
|
+
<StopIcon className={cls.stopIcon}/>
|
|
26
|
+
<p className={cls.runText}>Stop</p>
|
|
27
|
+
</button>
|
|
28
|
+
<button className={cls.saveButton} onClick={props.save}>
|
|
29
|
+
<SaveIcon className={cls.saveIcon}/>
|
|
30
|
+
<p className={cls.runText}>Save</p>
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useState } from "react";
|
|
2
|
+
import type { EditorDocument } from "../types/EditorDocument";
|
|
3
|
+
import { FileApi, ProjectApi, CompilerApi } from "../api";
|
|
4
|
+
|
|
5
|
+
export function useCompiler(initialFiles?: Record<string, string>) {
|
|
6
|
+
|
|
7
|
+
const [projectId, setProjectId] = useState<string>("");
|
|
8
|
+
const [output, setOutput] = useState<string>("");
|
|
9
|
+
|
|
10
|
+
const fileApi = new FileApi();
|
|
11
|
+
const projectApi = new ProjectApi();
|
|
12
|
+
const compilerApi = new CompilerApi();
|
|
13
|
+
|
|
14
|
+
useLayoutEffect(() => {
|
|
15
|
+
projectApi.apiProjectsCreatePost({ name: "AHAHHAHAHA" })
|
|
16
|
+
.then(res => {
|
|
17
|
+
setProjectId(res.data.projectId);
|
|
18
|
+
})
|
|
19
|
+
.catch(err => alert(err))
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
const [documents, setDocuments] = useState<EditorDocument[]>([]);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (projectId && initialFiles) {
|
|
27
|
+
setDocuments([]);
|
|
28
|
+
Object.keys(initialFiles).forEach(key => {
|
|
29
|
+
console.log(key, initialFiles[key]);
|
|
30
|
+
|
|
31
|
+
fileApi.apiFilesProjectProjectIdPost(projectId, {
|
|
32
|
+
name: key,
|
|
33
|
+
path: key
|
|
34
|
+
}).then(res => {
|
|
35
|
+
const file: EditorDocument = {
|
|
36
|
+
id: res.data,
|
|
37
|
+
content: initialFiles[key],
|
|
38
|
+
language: "csharp",
|
|
39
|
+
modified: false,
|
|
40
|
+
name: key,
|
|
41
|
+
path: key
|
|
42
|
+
};
|
|
43
|
+
setDocuments(docs => [...docs, file]);
|
|
44
|
+
fileApi.apiFilesFileIdSavePost(file.id, {
|
|
45
|
+
content: initialFiles[key],
|
|
46
|
+
})
|
|
47
|
+
.then(res => console.log(res))
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}, [projectId]);
|
|
52
|
+
|
|
53
|
+
const [selectedId, setSelectedId] = useState<string | null>(
|
|
54
|
+
() => documents[0]?.id || null
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const selectedDocument = documents.find(d => d.id === selectedId) || null;
|
|
58
|
+
|
|
59
|
+
const setDocumentContent = (id: string, newContent: string) => {
|
|
60
|
+
setDocuments(docs =>
|
|
61
|
+
docs.map(d =>
|
|
62
|
+
d.id === id
|
|
63
|
+
? { ...d, content: newContent, modified: true }
|
|
64
|
+
: d
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// В useCompiler.ts обновляем функцию addDocument:
|
|
70
|
+
const addDocument = (fileName?: string) => {
|
|
71
|
+
// Если передано имя файла - используем его, иначе генерируем
|
|
72
|
+
const defaultName = `file${documents.length + 1}.cs`;
|
|
73
|
+
const finalName = fileName || defaultName;
|
|
74
|
+
|
|
75
|
+
let fileId = "";
|
|
76
|
+
|
|
77
|
+
fileApi.apiFilesProjectProjectIdPost(projectId, {
|
|
78
|
+
name: finalName,
|
|
79
|
+
path: finalName
|
|
80
|
+
})
|
|
81
|
+
.then(res => {
|
|
82
|
+
fileId = res.data;
|
|
83
|
+
|
|
84
|
+
// Определяем язык по расширению
|
|
85
|
+
let language: "javascript" | "csharp" = "csharp";
|
|
86
|
+
if (finalName.endsWith('.js')) {
|
|
87
|
+
language = "javascript";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Начальное содержимое в зависимости от языка
|
|
91
|
+
let initialContent = "// New file";
|
|
92
|
+
if (language === "javascript") {
|
|
93
|
+
initialContent = "// JavaScript file";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const newDoc: EditorDocument = {
|
|
97
|
+
id: fileId,
|
|
98
|
+
path: finalName,
|
|
99
|
+
name: finalName,
|
|
100
|
+
language: language,
|
|
101
|
+
content: initialContent,
|
|
102
|
+
modified: false,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
setDocuments(d => [...d, newDoc]);
|
|
106
|
+
setSelectedId(newDoc.id);
|
|
107
|
+
|
|
108
|
+
// Сохраняем начальное содержимое
|
|
109
|
+
fileApi.apiFilesFileIdSavePost(fileId, {
|
|
110
|
+
content: initialContent,
|
|
111
|
+
}).catch(err => console.error("Ошибка при сохранении:", err));
|
|
112
|
+
})
|
|
113
|
+
.catch(err => {
|
|
114
|
+
console.error("Ошибка при создании файла:", err);
|
|
115
|
+
alert(`Ошибка при создании файла: ${err.message}`);
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const updateDocument = (id: string, patch: Partial<EditorDocument>) => {
|
|
120
|
+
const doc = documents.find(d => d.id === id);
|
|
121
|
+
if (!doc) return;
|
|
122
|
+
|
|
123
|
+
// 1. Локальное обновление
|
|
124
|
+
setDocuments(docs =>
|
|
125
|
+
docs.map(doc => doc.id === id ? { ...doc, ...patch, modified: true } : doc)
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// 2. Если меняется имя - отправить на сервер
|
|
129
|
+
if (patch.name !== undefined && patch.name !== doc.name) {
|
|
130
|
+
fileApi.apiFilesFileIdRenamePost(id, {
|
|
131
|
+
name: patch.name
|
|
132
|
+
}).catch(err => {
|
|
133
|
+
console.error("Ошибка при переименовании:", err);
|
|
134
|
+
// Откат если ошибка
|
|
135
|
+
setDocuments(docs =>
|
|
136
|
+
docs.map(d => d.id === id ? { ...d, name: doc.name } : d)
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 3. Если меняется контент - сохранить
|
|
142
|
+
if (patch.modified) {
|
|
143
|
+
fileApi.apiFilesFileIdSavePost(id, {
|
|
144
|
+
content: patch.content,
|
|
145
|
+
}).catch(err => console.error("Ошибка при сохранении:", err));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
const deleteDocument = (id: string) => {
|
|
151
|
+
fileApi.apiFilesFileIdDeletePost(id)
|
|
152
|
+
.then(() => setDocuments(docs => docs.filter(doc => doc.id !== id)))
|
|
153
|
+
.catch(err => alert(err));
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const saveAll = () => {
|
|
157
|
+
// Находим измененные документы
|
|
158
|
+
const modifiedDocs = documents.filter(doc => doc.modified);
|
|
159
|
+
|
|
160
|
+
if (modifiedDocs.length === 0) {
|
|
161
|
+
console.log("Нет изменений для сохранения");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log(`Сохранение ${modifiedDocs.length} файлов`);
|
|
166
|
+
|
|
167
|
+
// Создаем массив промисов для сохранения
|
|
168
|
+
const savePromises = modifiedDocs.map(doc =>
|
|
169
|
+
fileApi.apiFilesFileIdSavePost(doc.id, {
|
|
170
|
+
content: doc.content
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// Выполняем все запросы
|
|
175
|
+
Promise.all(savePromises)
|
|
176
|
+
.then(() => {
|
|
177
|
+
// После успешного сохранения всех файлов сбрасываем флаг modified
|
|
178
|
+
setDocuments(docs =>
|
|
179
|
+
docs.map(doc => ({
|
|
180
|
+
...doc,
|
|
181
|
+
// Если документ был среди измененных - сбрасываем флаг
|
|
182
|
+
modified: modifiedDocs.some(md => md.id === doc.id) ? false : doc.modified
|
|
183
|
+
}))
|
|
184
|
+
);
|
|
185
|
+
console.log("Все файлы сохранены");
|
|
186
|
+
})
|
|
187
|
+
.catch(error => {
|
|
188
|
+
console.error("Ошибка при сохранении:", error);
|
|
189
|
+
alert("Ошибка сохранения файлов");
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const run = async () => {
|
|
194
|
+
await saveAll()
|
|
195
|
+
setOutput("Запуск программы...")
|
|
196
|
+
const res = await compilerApi.apiCompileProjectProjectIdRunPost(projectId, {
|
|
197
|
+
mainFile: "ConsoleApp.csproj"
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
setOutput(res.data.output ?? "");
|
|
201
|
+
await stop();
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
const stop = () => {
|
|
205
|
+
compilerApi.apiCompileProjectProjectIdStopPost(projectId)
|
|
206
|
+
.then(res => console.log(res.data))
|
|
207
|
+
.catch(err => alert(err));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
documents,
|
|
214
|
+
selectedDocument,
|
|
215
|
+
selectedId,
|
|
216
|
+
setSelectedId,
|
|
217
|
+
setDocumentContent,
|
|
218
|
+
addDocument,
|
|
219
|
+
updateDocument,
|
|
220
|
+
deleteDocument,
|
|
221
|
+
run,
|
|
222
|
+
stop,
|
|
223
|
+
output,
|
|
224
|
+
saveAll,
|
|
225
|
+
history: [],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
File without changes
|
package/src/index.css
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#app {
|
|
17
|
+
width: 100vw;
|
|
18
|
+
height: 100vh;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
a {
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
color: #646cff;
|
|
24
|
+
text-decoration: inherit;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a:hover {
|
|
28
|
+
color: #535bf2;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
body {
|
|
32
|
+
margin: 0;
|
|
33
|
+
display: flex;
|
|
34
|
+
place-items: center;
|
|
35
|
+
min-width: 320px;
|
|
36
|
+
min-height: 100vh;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
h1 {
|
|
40
|
+
font-size: 3.2em;
|
|
41
|
+
line-height: 1.1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
button {
|
|
45
|
+
border-radius: 8px;
|
|
46
|
+
border: 1px solid transparent;
|
|
47
|
+
padding: 0.6em 1.2em;
|
|
48
|
+
font-size: 1em;
|
|
49
|
+
font-weight: 500;
|
|
50
|
+
font-family: inherit;
|
|
51
|
+
background-color: #1a1a1a;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
transition: border-color 0.25s;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
button:hover {
|
|
57
|
+
border-color: #646cff;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
button:focus,
|
|
61
|
+
button:focus-visible {
|
|
62
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (prefers-color-scheme: light) {
|
|
66
|
+
:root {
|
|
67
|
+
color: #213547;
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
a:hover {
|
|
72
|
+
color: #747bff;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
button {
|
|
76
|
+
background-color: #f9f9f9;
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/main.tsx
ADDED