vzcode 0.5.0 → 0.6.0
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/README.md +21 -5
- package/dist/assets/index-41607816.js +89 -0
- package/dist/assets/index-8bac68c9.css +1 -0
- package/dist/index.html +16 -2
- package/package.json +25 -20
- package/src/client/{App.jsx → App.tsx} +68 -60
- package/src/client/Sidebar/{Directory.jsx → DirectoryListing.tsx} +27 -13
- package/src/client/Sidebar/{File.jsx → FileListing.tsx} +14 -4
- package/src/client/Sidebar/Listing.tsx +44 -0
- package/src/client/Sidebar/index.tsx +80 -0
- package/src/client/Sidebar/styles.scss +84 -0
- package/src/client/Sidebar/{useOpenDirectories.js → useOpenDirectories.ts} +4 -6
- package/src/client/{getFileTree.js → getFileTree.ts} +6 -3
- package/src/client/getOrCreateEditor.js +5 -4
- package/src/client/settings.jsx +22 -66
- package/src/client/{sortFileTree.js → sortFileTree.ts} +7 -3
- package/src/client/style.scss +93 -0
- package/src/server/index.js +0 -0
- package/src/types.ts +57 -0
- package/dist/assets/index-29b6a606.css +0 -1
- package/dist/assets/index-523ecad7.js +0 -89
- package/src/client/Sidebar/FileOrDirectory.jsx +0 -33
- package/src/client/Sidebar/index.jsx +0 -64
- package/src/client/Sidebar/styles.css +0 -88
- package/src/client/style.css +0 -120
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { EditorView, basicSetup } from 'codemirror';
|
|
2
|
-
import { EditorState } from '@codemirror/state';
|
|
2
|
+
import { Compartment, EditorState } from '@codemirror/state';
|
|
3
3
|
import { javascript } from '@codemirror/lang-javascript';
|
|
4
4
|
import { markdown } from '@codemirror/lang-markdown';
|
|
5
5
|
import { html } from '@codemirror/lang-html';
|
|
6
6
|
import { css } from '@codemirror/lang-css';
|
|
7
|
-
import { oneDark } from '@codemirror/theme-one-dark';
|
|
8
7
|
import { json1Sync } from 'codemirror-ot';
|
|
9
8
|
import { json1Presence, textUnicode } from '../ot';
|
|
10
9
|
import { json1PresenceBroadcast } from './json1PresenceBroadcast';
|
|
@@ -23,6 +22,7 @@ export const getOrCreateEditor = ({
|
|
|
23
22
|
shareDBDoc,
|
|
24
23
|
localPresence,
|
|
25
24
|
docPresence,
|
|
25
|
+
theme
|
|
26
26
|
}) => {
|
|
27
27
|
const data = shareDBDoc.data;
|
|
28
28
|
|
|
@@ -31,6 +31,8 @@ export const getOrCreateEditor = ({
|
|
|
31
31
|
// The path for this file in the ShareDB document.
|
|
32
32
|
const path = [fileId, 'text'];
|
|
33
33
|
|
|
34
|
+
let themeSet = new Compartment();
|
|
35
|
+
|
|
34
36
|
const extensions = [
|
|
35
37
|
// This plugin implements multiplayer editing,
|
|
36
38
|
// real-time synchronozation of changes across clients.
|
|
@@ -49,7 +51,7 @@ export const getOrCreateEditor = ({
|
|
|
49
51
|
json1PresenceDisplay({ path, docPresence }),
|
|
50
52
|
|
|
51
53
|
basicSetup,
|
|
52
|
-
|
|
54
|
+
themeSet.of(theme),
|
|
53
55
|
];
|
|
54
56
|
|
|
55
57
|
if (
|
|
@@ -69,7 +71,6 @@ export const getOrCreateEditor = ({
|
|
|
69
71
|
|
|
70
72
|
let editor = editorCache.get(fileId);
|
|
71
73
|
if (!editor) {
|
|
72
|
-
// Cache miss --> mint a new editor.
|
|
73
74
|
editor = new EditorView({
|
|
74
75
|
state: EditorState.create({
|
|
75
76
|
doc: data[fileId].text,
|
package/src/client/settings.jsx
CHANGED
|
@@ -3,75 +3,28 @@ import Modal from 'react-bootstrap/Modal';
|
|
|
3
3
|
import Form from 'react-bootstrap/Form';
|
|
4
4
|
import Button from 'react-bootstrap/Button';
|
|
5
5
|
import Select from 'react-select';
|
|
6
|
+
import { oneDark } from '@codemirror/theme-one-dark';
|
|
7
|
+
import { okaidia } from '@uiw/codemirror-theme-okaidia';
|
|
8
|
+
import { abcdef } from '@uiw/codemirror-theme-abcdef';
|
|
9
|
+
import { dracula } from '@uiw/codemirror-theme-dracula';
|
|
10
|
+
import { eclipse } from '@uiw/codemirror-theme-eclipse';
|
|
11
|
+
import { githubDark } from '@uiw/codemirror-theme-github';
|
|
12
|
+
import { material } from '@uiw/codemirror-theme-material';
|
|
13
|
+
import { nord } from '@uiw/codemirror-theme-nord';
|
|
14
|
+
import { xcodeLight } from '@uiw/codemirror-theme-xcode';
|
|
6
15
|
|
|
7
16
|
// TODO document where this list came from
|
|
8
17
|
// TODO research which themes are available for CodeMirror 6
|
|
9
18
|
const themes = [
|
|
10
|
-
{ value:
|
|
11
|
-
{ value:
|
|
12
|
-
{ value:
|
|
13
|
-
{ value:
|
|
14
|
-
{ value:
|
|
15
|
-
{ value:
|
|
16
|
-
{ value:
|
|
17
|
-
{ value:
|
|
18
|
-
{ value:
|
|
19
|
-
{ value: 'base16-light', label: 'base16-light' },
|
|
20
|
-
{ value: 'bespin', label: 'bespin' },
|
|
21
|
-
{ value: 'blackboard', label: 'blackboard' },
|
|
22
|
-
{ value: 'cobalt', label: 'cobalt' },
|
|
23
|
-
{ value: 'colorforth', label: 'colorforth' },
|
|
24
|
-
{ value: 'darcula', label: 'darcula' },
|
|
25
|
-
{ value: 'duotone-dark', label: 'duotone-dark' },
|
|
26
|
-
{ value: 'duotone-light', label: 'duotone-light' },
|
|
27
|
-
{ value: 'eclipse', label: 'eclipse' },
|
|
28
|
-
{ value: 'elegant', label: 'elegant' },
|
|
29
|
-
{ value: 'erlang-dark', label: 'erlang-dark' },
|
|
30
|
-
{ value: 'gruvbox-dark', label: 'gruvbox-dark' },
|
|
31
|
-
{ value: 'hopscotch', label: 'hopscotch' },
|
|
32
|
-
{ value: 'icecoder', label: 'icecoder' },
|
|
33
|
-
{ value: 'idea', label: 'idea' },
|
|
34
|
-
{ value: 'isotope', label: 'isotope' },
|
|
35
|
-
{ value: 'juejin', label: 'juejin' },
|
|
36
|
-
{ value: 'lesser-dark', label: 'lesser-dark' },
|
|
37
|
-
{ value: 'liquibyte', label: 'liquibyte' },
|
|
38
|
-
{ value: 'lucario', label: 'lucario' },
|
|
39
|
-
{ value: 'material', label: 'material' },
|
|
40
|
-
{ value: 'material-darker', label: 'material-darker' },
|
|
41
|
-
{ value: 'material-palenight', label: 'material-palenight' },
|
|
42
|
-
{ value: 'material-ocean', label: 'material-ocean' },
|
|
43
|
-
{ value: 'mbo', label: 'mbo' },
|
|
44
|
-
{ value: 'mdn-like', label: 'mdn-like' },
|
|
45
|
-
{ value: 'midnight', label: 'midnight' },
|
|
46
|
-
{ value: 'monokai', label: 'monokai' },
|
|
47
|
-
{ value: 'moxer', label: 'moxer' },
|
|
48
|
-
{ value: 'neat', label: 'neat' },
|
|
49
|
-
{ value: 'neo', label: 'neo' },
|
|
50
|
-
{ value: 'night', label: 'night' },
|
|
51
|
-
{ value: 'nord', label: 'nord' },
|
|
52
|
-
{ value: 'oceanic-next', label: 'oceanic-next' },
|
|
53
|
-
{ value: 'OneDark', label: 'One Dark' },
|
|
54
|
-
{ value: 'panda-syntax', label: 'panda-syntax' },
|
|
55
|
-
{ value: 'paraiso-dark', label: 'paraiso-dark' },
|
|
56
|
-
{ value: 'paraiso-light', label: 'paraiso-light' },
|
|
57
|
-
{ value: 'pastel-on-dark', label: 'pastel-on-dark' },
|
|
58
|
-
{ value: 'railscasts', label: 'railscasts' },
|
|
59
|
-
{ value: 'rubyblue', label: 'rubyblue' },
|
|
60
|
-
{ value: 'seti', label: 'seti' },
|
|
61
|
-
{ value: 'shadowfox', label: 'shadowfox' },
|
|
62
|
-
{ value: 'solarized', label: 'solarized' },
|
|
63
|
-
{ value: 'ssms', label: 'ssms' },
|
|
64
|
-
{ value: 'the-matrix', label: 'the-matrix' },
|
|
65
|
-
{ value: 'tomorrow-night-bright', label: 'tomorrow-night-bright' },
|
|
66
|
-
{ value: 'tomorrow-night-eighties', label: 'tomorrow-night-eighties' },
|
|
67
|
-
{ value: 'ttcn', label: 'ttcn' },
|
|
68
|
-
{ value: 'twilight', label: 'twilight' },
|
|
69
|
-
{ value: 'vibrant-ink', label: 'vibrant-ink' },
|
|
70
|
-
{ value: 'xq-dark', label: 'xq-dark' },
|
|
71
|
-
{ value: 'xq-light', label: 'xq-light' },
|
|
72
|
-
{ value: 'yeti', label: 'yeti' },
|
|
73
|
-
{ value: 'yonce', label: 'yonce' },
|
|
74
|
-
{ value: 'zenburn', label: 'zenburn' },
|
|
19
|
+
{ value: abcdef, label: 'abcdef' },
|
|
20
|
+
{ value: dracula, label: 'darcula' },
|
|
21
|
+
{ value: eclipse, label: 'eclipse' },
|
|
22
|
+
{ value: material, label: 'material' },
|
|
23
|
+
{ value: nord, label: 'nord' },
|
|
24
|
+
{ value: oneDark, label: 'One Dark' },
|
|
25
|
+
{ value: okaidia, label: 'okaidia' },
|
|
26
|
+
{ value: githubDark, label: 'github' },
|
|
27
|
+
{ value: xcodeLight, label: 'xcode' },
|
|
75
28
|
];
|
|
76
29
|
|
|
77
30
|
const saveTimes = [
|
|
@@ -81,9 +34,12 @@ const saveTimes = [
|
|
|
81
34
|
{ value: 30, label: '30 seconds' },
|
|
82
35
|
];
|
|
83
36
|
|
|
84
|
-
export const Settings = ({ show, onClose, setTheme }) => {
|
|
37
|
+
export const Settings = ({ show, onClose, setTheme, editor }) => {
|
|
85
38
|
const handleChange = useCallback((selectedOption) => {
|
|
86
39
|
setTheme(selectedOption.value);
|
|
40
|
+
editor.dispatch({
|
|
41
|
+
effects: themeSet.reconfigure(selectedOption.value),
|
|
42
|
+
});
|
|
87
43
|
}, []);
|
|
88
44
|
|
|
89
45
|
const handleSaveTimeChange = useCallback((selectedOption) => {
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// Recursively sorts the file tree in-place.
|
|
2
2
|
// Sorts first to group directories before files.
|
|
3
3
|
// Sorts second alphabetically.
|
|
4
|
+
|
|
5
|
+
import { FileTree, FileTreeFile } from '../types';
|
|
6
|
+
|
|
4
7
|
// From https://github.com/vizhub-core/vizhub/blob/main/vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/FileTree/sortFileTree.js
|
|
5
|
-
export const sortFileTree = (fileTree) => {
|
|
8
|
+
export const sortFileTree = (fileTree: FileTree) => {
|
|
6
9
|
if (fileTree.children) {
|
|
7
10
|
fileTree.children.sort((a, b) => {
|
|
8
|
-
const aIsFile = a.file ? 1 : 0;
|
|
9
|
-
const bIsFile = b.file ? 1 : 0;
|
|
11
|
+
const aIsFile = (a as FileTreeFile).file ? 1 : 0;
|
|
12
|
+
const bIsFile = (b as FileTreeFile).file ? 1 : 0;
|
|
13
|
+
// Directories before files.
|
|
10
14
|
return aIsFile - bIsFile || a.name.localeCompare(b.name);
|
|
11
15
|
});
|
|
12
16
|
fileTree.children.forEach(sortFileTree);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--vzcode-font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
|
|
3
|
+
Liberation Mono, monospace;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/* width */
|
|
7
|
+
::-webkit-scrollbar {
|
|
8
|
+
width: 10px;
|
|
9
|
+
height: 10px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Track */
|
|
13
|
+
::-webkit-scrollbar-track {
|
|
14
|
+
background: rgb(41, 44, 52);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Handle */
|
|
18
|
+
::-webkit-scrollbar-thumb {
|
|
19
|
+
background: rgb(37, 37, 38);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Handle on hover */
|
|
23
|
+
::-webkit-scrollbar-thumb:hover {
|
|
24
|
+
background: #555;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
html,
|
|
28
|
+
body,
|
|
29
|
+
#root,
|
|
30
|
+
.app {
|
|
31
|
+
height: 100%;
|
|
32
|
+
}
|
|
33
|
+
.app {
|
|
34
|
+
/* TODO use a variable for this */
|
|
35
|
+
background-color: rgb(41, 44, 52);
|
|
36
|
+
|
|
37
|
+
font-family: 'Poppins', sans-serif;
|
|
38
|
+
display: flex;
|
|
39
|
+
|
|
40
|
+
.left {
|
|
41
|
+
display: flex;
|
|
42
|
+
}
|
|
43
|
+
.right {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex: 1;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
min-width: 0;
|
|
48
|
+
|
|
49
|
+
.tab-list {
|
|
50
|
+
display: flex;
|
|
51
|
+
background-color: rgb(37, 37, 38);
|
|
52
|
+
|
|
53
|
+
.tab {
|
|
54
|
+
background: rgb(45, 45, 45);
|
|
55
|
+
color: #fff;
|
|
56
|
+
font-family: var(--vzcode-font-family);
|
|
57
|
+
align-items: center;
|
|
58
|
+
display: flex;
|
|
59
|
+
padding-top: 2px;
|
|
60
|
+
padding-left: 10px;
|
|
61
|
+
padding-right: 10px;
|
|
62
|
+
border-top-left-radius: 10px;
|
|
63
|
+
border-top-right-radius: 10px;
|
|
64
|
+
margin-top: 5px;
|
|
65
|
+
margin-left: 2px;
|
|
66
|
+
margin-right: 2px;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
|
|
69
|
+
.tab-close {
|
|
70
|
+
margin-left: 5px;
|
|
71
|
+
}
|
|
72
|
+
.tab-close:hover {
|
|
73
|
+
border-radius: 30%;
|
|
74
|
+
background-color: rgb(37, 37, 38);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
.tab.active {
|
|
78
|
+
background-color: rgb(41, 44, 52);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.editor {
|
|
83
|
+
flex: 1;
|
|
84
|
+
display: flex;
|
|
85
|
+
font-family: var(--vzcode-font-family);
|
|
86
|
+
overflow-x: auto;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.themes {
|
|
92
|
+
color: rgb(37, 37, 38);
|
|
93
|
+
}
|
package/src/server/index.js
CHANGED
|
File without changes
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// FileId
|
|
2
|
+
// * A unique ID for a file.
|
|
3
|
+
// * This is a random string.
|
|
4
|
+
export type FileId = string;
|
|
5
|
+
|
|
6
|
+
// Files
|
|
7
|
+
// * A collection of files.
|
|
8
|
+
// * Keys are _not_ file names or array indices,
|
|
9
|
+
// because based on past experience, that
|
|
10
|
+
// leads to very difficult frontend logic around
|
|
11
|
+
// OT in the case that a file is renamed or deleted.
|
|
12
|
+
// * When the file name changes, or files are added/deleted,
|
|
13
|
+
// this ID stays the same, simplifying things re:OT.
|
|
14
|
+
export interface Files {
|
|
15
|
+
[fileId: FileId]: File;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// File
|
|
19
|
+
// * A file with `name` and `text`.
|
|
20
|
+
export interface File {
|
|
21
|
+
// The file name.
|
|
22
|
+
// e.g. "index.html".
|
|
23
|
+
name: string;
|
|
24
|
+
|
|
25
|
+
// The text content of the file.
|
|
26
|
+
// e.g. "<body>Hello</body>"
|
|
27
|
+
text: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// FileTree
|
|
31
|
+
// * A tree of files.
|
|
32
|
+
// * Each node in the tree is either a directory or a file.
|
|
33
|
+
// * Each directory has a `children` array.
|
|
34
|
+
// * Each file has a `file` object.
|
|
35
|
+
// * Each file has a `fileId` string.
|
|
36
|
+
// * Each directory has a `name` string.
|
|
37
|
+
// * Each directory has a `path` string.
|
|
38
|
+
// * The `path` string is the path to the directory.
|
|
39
|
+
// e.g. "src/components".
|
|
40
|
+
// * The `path` string is the path to the file.
|
|
41
|
+
// e.g. "src/components/HelloWorld.js".
|
|
42
|
+
export interface FileTree {
|
|
43
|
+
name: string;
|
|
44
|
+
path?: string;
|
|
45
|
+
children?: Array<FileTree | FileTreeFile>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// FileTreeFile
|
|
49
|
+
// * A file in a file tree.
|
|
50
|
+
// * Each file has a `name` string.
|
|
51
|
+
// * Each file has a `file` object.
|
|
52
|
+
// * Each file has a `fileId` string.
|
|
53
|
+
export interface FileTreeFile {
|
|
54
|
+
name: string;
|
|
55
|
+
file: File;
|
|
56
|
+
fileId: FileId;
|
|
57
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap";@import"https://unpkg.com/boxicons@2.0.7/css/boxicons.min.css";@import"https://unpkg.com/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css";.vz-sidebar{position:fixed;top:0;left:0;height:100%;width:200px;background:rgb(54,65,89)}.vz-sidebar .full-box{padding:7px;display:flex;flex-direction:row;align-items:center;justify-content:space-between}.vz-sidebar .file-or-directory{display:flex;flex-direction:row;align-items:center;justify-content:space-between;cursor:pointer;margin:0 10px;color:#dbdde1;border-radius:5px}.vz-sidebar .link-name{margin-top:30px;margin-left:10px;color:#9aa0ac;font-size:12px;text-decoration:none}.vz-sidebar .new-btn{justify-content:right;margin-right:10px;cursor:pointer}.vz-sidebar .utils{display:flex}.vz-sidebar .utilities{margin-right:3px}.vz-sidebar .settings{position:absolute;bottom:0;height:30px;width:180px;z-index:100;color:#dbdde1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:14px 0;margin:10px;border-radius:5px}.vz-sidebar .file-or-directory:hover,.vz-sidebar .settings:hover{background-color:#4a5469}.vz-sidebar .name{display:flex;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.vz-sidebar .indentation{margin-left:20px}.vz-sidebar .arrow-wrapper{margin-right:4px}*{margin:0;padding:0;box-sizing:border-box}::-webkit-scrollbar{width:10px;height:20px}::-webkit-scrollbar-track{background:rgb(41,44,52)}::-webkit-scrollbar-thumb{background:rgb(37,37,38)}::-webkit-scrollbar-thumb:hover{background:#555}:root{--main-font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace}body{background:rgb(41,44,52);font-family:Poppins,sans-serif;overflow-x:hidden}.tab{width:max-content;height:30px;background:rgb(45,45,45);text-align:center;color:#fff;font-family:var(--main-font-family);justify-content:center;align-items:center;display:flex;padding-left:10px;padding-right:10px;border-top-left-radius:10px;border-top-right-radius:10px;margin-top:5px;margin-left:2px;margin-right:2px;cursor:pointer}.tab.active{background-color:#292c34}.tab-close{display:flex;cursor:pointer;margin-left:5px;justify-content:center;align-items:center}.tab-close:hover{border-radius:30%;background-color:#252526}.editor{position:relative;margin-left:200px;width:100%;height:100%;top:30px;bottom:0;background-color:#292c34;color:#fff;font-family:var(--main-font-family)}.tab-list{position:fixed;display:flex;flex-direction:row;top:0;left:200px;height:35px;width:100%;background:rgb(37,37,38);z-index:100;transition:all .5s ease}.bottom-bar{position:absolute;bottom:0;left:0;height:20px;width:100%;background:rgb(45,45,45);z-index:100;transition:all .5s ease}.themes{color:#252526}
|