vzcode 1.5.0 → 1.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/dist/index.html CHANGED
@@ -20,8 +20,8 @@
20
20
  href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
21
21
  rel="stylesheet"
22
22
  />
23
- <script type="module" crossorigin src="/assets/index-D6aZiqme.js"></script>
24
- <link rel="stylesheet" crossorigin href="/assets/index-ClPo_hzs.css">
23
+ <script type="module" crossorigin src="/assets/index-B2OgpmfL.js"></script>
24
+ <link rel="stylesheet" crossorigin href="/assets/index-DAYbg783.css">
25
25
  </head>
26
26
  <body>
27
27
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vzcode",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Multiplayer code editor system",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -91,6 +91,10 @@
91
91
  {
92
92
  "name": "Philip Park",
93
93
  "url": "https://github.com/philippark"
94
+ },
95
+ {
96
+ "name": "Jeffrey Cordero",
97
+ "url": "https://github.com/jeffrey-asm"
94
98
  }
95
99
  ],
96
100
  "license": "MIT",
@@ -99,7 +103,7 @@
99
103
  },
100
104
  "homepage": "https://github.com/vizhub-core/vzcode#readme",
101
105
  "dependencies": {
102
- "@codemirror/autocomplete": "^6.16.2",
106
+ "@codemirror/autocomplete": "^6.17.0",
103
107
  "@codemirror/lang-css": "^6.2.1",
104
108
  "@codemirror/lang-html": "^6.4.9",
105
109
  "@codemirror/lang-javascript": "^6.2.2",
@@ -107,7 +111,7 @@
107
111
  "@codemirror/lang-markdown": "^6.2.5",
108
112
  "@codemirror/state": "^6.4.1",
109
113
  "@codemirror/theme-one-dark": "^6.1.2",
110
- "@codemirror/view": "^6.28.1",
114
+ "@codemirror/view": "^6.28.4",
111
115
  "@lezer/highlight": "^1.2.0",
112
116
  "@replit/codemirror-indentation-markers": "^6.5.2",
113
117
  "@replit/codemirror-interact": "^6.3.1",
@@ -115,15 +119,15 @@
115
119
  "@replit/codemirror-vscode-keymap": "^6.0.2",
116
120
  "@teamwork/websocket-json-stream": "^2.0.0",
117
121
  "@typescript/vfs": "^1.5.3",
118
- "@uiw/codemirror-theme-abcdef": "^4.22.2",
119
- "@uiw/codemirror-theme-dracula": "^4.22.2",
120
- "@uiw/codemirror-theme-eclipse": "^4.22.2",
121
- "@uiw/codemirror-theme-github": "^4.22.2",
122
- "@uiw/codemirror-theme-material": "^4.22.2",
123
- "@uiw/codemirror-theme-nord": "^4.22.2",
124
- "@uiw/codemirror-theme-okaidia": "^4.22.2",
125
- "@uiw/codemirror-theme-xcode": "^4.22.2",
126
- "@uiw/codemirror-themes": "^4.22.2",
122
+ "@uiw/codemirror-theme-abcdef": "^4.23.0",
123
+ "@uiw/codemirror-theme-dracula": "^4.23.0",
124
+ "@uiw/codemirror-theme-eclipse": "^4.23.0",
125
+ "@uiw/codemirror-theme-github": "^4.23.0",
126
+ "@uiw/codemirror-theme-material": "^4.23.0",
127
+ "@uiw/codemirror-theme-nord": "^4.23.0",
128
+ "@uiw/codemirror-theme-okaidia": "^4.23.0",
129
+ "@uiw/codemirror-theme-xcode": "^4.23.0",
130
+ "@uiw/codemirror-themes": "^4.23.0",
127
131
  "body-parser": "^1.20.2",
128
132
  "codemirror": "^6.0.1",
129
133
  "codemirror-ot": "^4.4.0",
@@ -136,16 +140,16 @@
136
140
  "json0-ot-diff": "^1.1.2",
137
141
  "ngrok": "^4.3.3",
138
142
  "open": "^10.1.0",
139
- "openai": "^4.51.0",
140
- "prettier-plugin-svelte": "^3.2.4",
143
+ "openai": "^4.52.3",
144
+ "prettier-plugin-svelte": "^3.2.5",
141
145
  "react": "^18.3.1",
142
- "react-bootstrap": "^2.10.2",
146
+ "react-bootstrap": "^2.10.4",
143
147
  "react-dom": "^18.3.1",
144
- "react-router-dom": "^6.23.1",
148
+ "react-router-dom": "^6.24.1",
145
149
  "sharedb": "^5.0.2",
146
150
  "sharedb-client-browser": "^5.0.1",
147
151
  "vizhub-ui": "^3.23.0",
148
- "ws": "^8.17.0"
152
+ "ws": "^8.18.0"
149
153
  },
150
154
  "devDependencies": {
151
155
  "@types/react": "^18.3.3",
@@ -153,9 +157,9 @@
153
157
  "@vitejs/plugin-react": "^4.3.1",
154
158
  "concurrently": "^8.2.2",
155
159
  "prettier": "^3.3.2",
156
- "sass": "^1.77.5",
157
- "typescript": "^5.4.5",
158
- "vite": "^5.3.1",
160
+ "sass": "^1.77.6",
161
+ "typescript": "^5.5.3",
162
+ "vite": "^5.3.3",
159
163
  "vitest": "^1.6.0"
160
164
  },
161
165
  "optionalDependencies": {
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const CssSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M4.192 3.143h15.615l-1.42 16.034-6.404 1.812-6.369-1.813L4.192 3.143zM16.9 6.424l-9.8-.002.158 1.949 7.529.002-.189 2.02H9.66l.179 1.913h4.597l-.272 2.62-2.164.598-2.197-.603-.141-1.569h-1.94l.216 2.867L12 17.484l3.995-1.137.905-9.923z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,20 @@
1
+ // From Heroicons
2
+ export const FolderSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="none"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="currentColor"
12
+ >
13
+ <path
14
+ strokeLinecap="round"
15
+ strokeLinejoin="round"
16
+ d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z"
17
+ />
18
+ </svg>
19
+ );
20
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const HtmlSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M4.136 3.012h15.729l-1.431 16.15-6.451 1.826-6.414-1.826-1.433-16.15zm5.266 7.302l-.173-2.035 7.533.002.173-1.963-9.87-.002.522 5.998h6.835l-.243 2.566-2.179.602-2.214-.605-.141-1.58H7.691l.247 3.123L12 17.506l4.028-1.08.558-6.111H9.402v-.001z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const JavaScriptSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M3 3h18v18H3V3zm16.525 13.707c-.131-.821-.666-1.511-2.252-2.155-.552-.259-1.165-.438-1.349-.854-.068-.248-.078-.382-.034-.529.113-.484.687-.629 1.137-.495.293.09.563.315.732.676.775-.507.775-.507 1.316-.844-.203-.314-.304-.451-.439-.586-.473-.528-1.103-.798-2.126-.775l-.528.067c-.507.124-.991.395-1.283.754-.855.968-.608 2.655.427 3.354 1.023.765 2.521.933 2.712 1.653.18.878-.652 1.159-1.475 1.058-.607-.136-.945-.439-1.316-1.002l-1.372.788c.157.359.337.517.607.832 1.305 1.316 4.568 1.249 5.153-.754.021-.067.18-.528.056-1.237l.034.049zm-6.737-5.434h-1.686c0 1.453-.007 2.898-.007 4.354 0 .924.047 1.772-.104 2.033-.247.517-.886.451-1.175.359-.297-.146-.448-.349-.623-.641-.047-.078-.082-.146-.095-.146l-1.368.844c.229.473.563.879.994 1.137.641.383 1.502.507 2.404.305.588-.17 1.095-.519 1.358-1.059.384-.697.302-1.553.299-2.509.008-1.541 0-3.083 0-4.635l.003-.042z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const JsonSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M5 3h2v2H5v5a2 2 0 01-2 2 2 2 0 012 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 00-2-2H0v-2h1a2 2 0 002-2V5a2 2 0 012-2m14 0a2 2 0 012 2v4a2 2 0 002 2h1v2h-1a2 2 0 00-2 2v4a2 2 0 01-2 2h-2v-2h2v-5a2 2 0 012-2 2 2 0 01-2-2V5h-2V3h2m-7 12a1 1 0 011 1 1 1 0 01-1 1 1 1 0 01-1-1 1 1 0 011-1m-4 0a1 1 0 011 1 1 1 0 01-1 1 1 1 0 01-1-1 1 1 0 011-1m8 0a1 1 0 011 1 1 1 0 01-1 1 1 1 0 01-1-1 1 1 0 011-1z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const MarkdownSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M20.56 18H3.44C2.65 18 2 17.37 2 16.59V7.41C2 6.63 2.65 6 3.44 6h17.12c.79 0 1.44.63 1.44 1.41v9.18c0 .78-.65 1.41-1.44 1.41M6.81 15.19v-3.66l1.92 2.35 1.92-2.35v3.66h1.93V8.81h-1.93l-1.92 2.35-1.92-2.35H4.89v6.38h1.92M19.69 12h-1.92V8.81h-1.92V12h-1.93l2.89 3.28L19.69 12z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,14 @@
1
+ // From https://primer.style/foundations/icons/pin-24
2
+ export const PinSVG = () => (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ viewBox="0 0 24 24"
6
+ width="24"
7
+ height="24"
8
+ >
9
+ <path
10
+ fill="currentColor"
11
+ d="m16.114 1.553 6.333 6.333a1.75 1.75 0 0 1-.603 2.869l-1.63.633a5.67 5.67 0 0 0-3.395 3.725l-1.131 3.959a1.75 1.75 0 0 1-2.92.757L9 16.061l-5.595 5.594a.749.749 0 1 1-1.06-1.06L7.939 15l-3.768-3.768a1.75 1.75 0 0 1 .757-2.92l3.959-1.131a5.666 5.666 0 0 0 3.725-3.395l.633-1.63a1.75 1.75 0 0 1 2.869-.603ZM5.232 10.171l8.597 8.597a.25.25 0 0 0 .417-.108l1.131-3.959A7.17 7.17 0 0 1 19.67 9.99l1.63-.634a.25.25 0 0 0 .086-.409l-6.333-6.333a.25.25 0 0 0-.409.086l-.634 1.63a7.17 7.17 0 0 1-4.711 4.293L5.34 9.754a.25.25 0 0 0-.108.417Z"
12
+ ></path>
13
+ </svg>
14
+ );
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const ReactSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M14.23 12.004a2.236 2.236 0 01-2.235 2.236 2.236 2.236 0 01-2.236-2.236 2.236 2.236 0 012.235-2.236 2.236 2.236 0 012.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38a2.167 2.167 0 00-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44a23.476 23.476 0 00-3.107-.534A23.892 23.892 0 0012.769 4.7c1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442a22.73 22.73 0 00-3.113.538 15.02 15.02 0 01-.254-1.42c-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87a25.64 25.64 0 01-4.412.005 26.64 26.64 0 01-1.183-1.86c-.372-.64-.71-1.29-1.018-1.946a25.17 25.17 0 011.013-1.954c.38-.66.773-1.286 1.18-1.868A25.245 25.245 0 0112 8.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933a25.952 25.952 0 00-1.345-2.32zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493a23.966 23.966 0 00-1.1-2.98c.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98a23.142 23.142 0 00-1.086 2.964c-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39a25.819 25.819 0 001.341-2.338zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143a22.005 22.005 0 01-2.006-.386c.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295a1.185 1.185 0 01-.553-.132c-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,19 @@
1
+ export const SearchFileSVG = () => {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ fill="none"
8
+ viewBox="0 0 24 24"
9
+ >
10
+ <path
11
+ stroke="currentColor"
12
+ strokeLinecap="round"
13
+ strokeLinejoin="round"
14
+ strokeWidth="1.5"
15
+ d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
16
+ />
17
+ </svg>
18
+ );
19
+ };
@@ -0,0 +1,20 @@
1
+ // From Heroicons
2
+ export const SearchSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="none"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="currentColor"
12
+ >
13
+ <path
14
+ strokeLinecap="round"
15
+ strokeLinejoin="round"
16
+ d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
17
+ />
18
+ </svg>
19
+ );
20
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const SvelteSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M10.354 21.125a4.44 4.44 0 01-4.765-1.767 4.109 4.109 0 01-.703-3.107 3.898 3.898 0 01.134-.522l.105-.321.287.21a7.21 7.21 0 002.186 1.092l.208.063-.02.208a1.253 1.253 0 00.226.83 1.337 1.337 0 001.435.533 1.231 1.231 0 00.343-.15l5.59-3.562a1.164 1.164 0 00.524-.778 1.242 1.242 0 00-.211-.937 1.338 1.338 0 00-1.435-.533 1.23 1.23 0 00-.343.15l-2.133 1.36a4.078 4.078 0 01-1.135.499 4.44 4.44 0 01-4.765-1.766 4.108 4.108 0 01-.702-3.108 3.855 3.855 0 011.742-2.582l5.589-3.563a4.072 4.072 0 011.135-.499 4.44 4.44 0 014.765 1.767 4.109 4.109 0 01.703 3.107 3.943 3.943 0 01-.134.522l-.105.321-.286-.21a7.204 7.204 0 00-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 00-.226-.831 1.337 1.337 0 00-1.435-.532 1.231 1.231 0 00-.343.15L8.62 9.368a1.162 1.162 0 00-.524.778 1.24 1.24 0 00.211.937 1.338 1.338 0 001.435.533 1.235 1.235 0 00.344-.151l2.132-1.36a4.067 4.067 0 011.135-.498 4.44 4.44 0 014.765 1.766 4.108 4.108 0 01.702 3.108 3.857 3.857 0 01-1.742 2.583l-5.589 3.562a4.072 4.072 0 01-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 00-2.896 4.295 6.753 6.753 0 00.666 4.336 6.43 6.43 0 00-.96 2.396 6.833 6.833 0 001.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 002.896-4.295 6.756 6.756 0 00-.665-4.336 6.429 6.429 0 00.958-2.396 6.831 6.831 0 00-1.167-5.168z" />
14
+ </svg>
15
+ );
16
+ };
@@ -0,0 +1,16 @@
1
+ // https://reactsvgicons.com/
2
+ export const TypeScriptSVG = () => {
3
+ return (
4
+ <svg
5
+ width="24"
6
+ height="24"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 24 24"
10
+ strokeWidth="1.5"
11
+ stroke="none"
12
+ >
13
+ <path d="M3 3h18v18H3V3m10.71 14.86c.5.98 1.51 1.73 3.09 1.73 1.6 0 2.8-.83 2.8-2.36 0-1.41-.81-2.04-2.25-2.66l-.42-.18c-.73-.31-1.04-.52-1.04-1.02 0-.41.31-.73.81-.73.48 0 .8.21 1.09.73l1.31-.87c-.55-.96-1.33-1.33-2.4-1.33-1.51 0-2.48.96-2.48 2.23 0 1.38.81 2.03 2.03 2.55l.42.18c.78.34 1.24.55 1.24 1.13 0 .48-.45.83-1.15.83-.83 0-1.31-.43-1.67-1.03l-1.38.8M13 11.25H8v1.5h1.5V20h1.75v-7.25H13v-1.5z" />
14
+ </svg>
15
+ );
16
+ };
@@ -10,3 +10,14 @@ export { FileSVG } from './FileSVG';
10
10
  export { DirectoryArrowSVG } from './DirectoryArrowSVG';
11
11
  export { PlaySVG } from './PlaySVG';
12
12
  export { QuestionMarkSVG } from './QuestionMarkSVG';
13
+ export { FolderSVG } from './FolderSVG';
14
+ export { SearchSVG } from './SearchSVG';
15
+ export { SearchFileSVG } from './SearchFileSVG';
16
+ export { JavaScriptSVG } from './JavaScriptSVG';
17
+ export { TypeScriptSVG } from './TypeScriptSVG';
18
+ export { ReactSVG } from './ReactSVG';
19
+ export { SvelteSVG } from './SvelteSVG';
20
+ export { HtmlSVG } from './HtmlSVG';
21
+ export { CssSVG } from './CssSVG';
22
+ export { JsonSVG } from './JsonSVG';
23
+ export { MarkdownSVG } from './MarkdownSVG';
@@ -6,13 +6,14 @@ import {
6
6
  useRef,
7
7
  } from 'react';
8
8
  import {
9
- FileId,
10
9
  Files,
11
10
  ItemId,
12
11
  ShareDBDoc,
13
12
  SubmitOperation,
14
13
  Username,
15
14
  VZCodeContent,
15
+ SearchResults,
16
+ SearchFileVisibility,
16
17
  } from '../types';
17
18
  import { usePrettier } from './usePrettier';
18
19
  import { useTypeScript } from './useTypeScript';
@@ -112,6 +113,19 @@ export type VZCodeContextValue = {
112
113
 
113
114
  typeScriptWorker: Worker | null;
114
115
 
116
+ search: SearchResults;
117
+ isSearchOpen: boolean;
118
+ setIsSearchOpen: (isSearchOpen: boolean) => void;
119
+ setSearch: (pattern: string) => void;
120
+ setSearchResults: (
121
+ files: ShareDBDoc<VZCodeContent>,
122
+ ) => void;
123
+ setSearchFileVisibility: (
124
+ files: ShareDBDoc<VZCodeContent>,
125
+ id: string,
126
+ visibility: SearchFileVisibility,
127
+ ) => void;
128
+
115
129
  isCreateFileModalOpen: boolean;
116
130
  handleOpenCreateFileModal: () => void;
117
131
  handleCloseCreateFileModal: () => void;
@@ -216,6 +230,8 @@ export const VZCodeProvider = ({
216
230
  tabList,
217
231
  activeFileId,
218
232
  theme,
233
+ search,
234
+ isSearchOpen,
219
235
  isSettingsOpen,
220
236
  isDocOpen,
221
237
  editorWantsFocus,
@@ -230,6 +246,10 @@ export const VZCodeProvider = ({
230
246
  openTab,
231
247
  closeTabs,
232
248
  setTheme,
249
+ setIsSearchOpen,
250
+ setSearch,
251
+ setSearchResults,
252
+ setSearchFileVisibility,
233
253
  setIsSettingsOpen,
234
254
  setIsDocOpen,
235
255
  closeSettings,
@@ -359,6 +379,13 @@ export const VZCodeProvider = ({
359
379
  openTab,
360
380
  closeTabs,
361
381
 
382
+ search,
383
+ isSearchOpen,
384
+ setIsSearchOpen,
385
+ setSearch,
386
+ setSearchResults,
387
+ setSearchFileVisibility,
388
+
362
389
  isSettingsOpen,
363
390
  setIsSettingsOpen,
364
391
  closeSettings,
@@ -0,0 +1,242 @@
1
+ import {
2
+ JavaScriptSVG,
3
+ TypeScriptSVG,
4
+ ReactSVG,
5
+ SvelteSVG,
6
+ JsonSVG,
7
+ MarkdownSVG,
8
+ HtmlSVG,
9
+ CssSVG,
10
+ SearchFileSVG,
11
+ DirectoryArrowSVG,
12
+ CloseSVG,
13
+ } from '../Icons';
14
+ import {
15
+ useRef,
16
+ useEffect,
17
+ useContext,
18
+ useState,
19
+ } from 'react';
20
+ import { Form } from '../bootstrap';
21
+ import { VZCodeContext } from '../VZCodeContext';
22
+ import { SearchFile } from '../../types';
23
+ import { EditorView } from 'codemirror';
24
+
25
+ function getExtensionIcon(extension: string) {
26
+ switch (extension) {
27
+ case 'jsx':
28
+ case 'tsx':
29
+ return <ReactSVG />;
30
+ case 'js':
31
+ return <JavaScriptSVG />;
32
+ case 'ts':
33
+ return <TypeScriptSVG />;
34
+ case 'json':
35
+ return <JsonSVG />;
36
+ case 'md':
37
+ return <MarkdownSVG />;
38
+ case 'html':
39
+ return <HtmlSVG />;
40
+ case 'css':
41
+ return <CssSVG />;
42
+ case 'svelte':
43
+ return <SvelteSVG />;
44
+ default:
45
+ return <SearchFileSVG />;
46
+ }
47
+ }
48
+
49
+ function jumpToPattern(
50
+ editor: EditorView,
51
+ pattern: string,
52
+ line: number,
53
+ index: number,
54
+ ) {
55
+ const position: number =
56
+ editor.state.doc.line(line).from + index;
57
+
58
+ editor.dispatch({
59
+ selection: {
60
+ anchor: position,
61
+ head: position + pattern.length,
62
+ },
63
+ scrollIntoView: true,
64
+ effects: EditorView.scrollIntoView(position, {
65
+ y: 'center',
66
+ }),
67
+ });
68
+ }
69
+
70
+ export const Search = () => {
71
+ const inputRef = useRef(null);
72
+ const [isMounted, setIsMounted] = useState(false);
73
+ const [isSearching, setIsSearching] = useState(false);
74
+ const {
75
+ search,
76
+ setSearch,
77
+ setActiveFileId,
78
+ openTab,
79
+ setSearchResults,
80
+ setSearchFileVisibility,
81
+ shareDBDoc,
82
+ editorCache,
83
+ } = useContext(VZCodeContext);
84
+ const { pattern, results } = search;
85
+
86
+ useEffect(() => {
87
+ if (isMounted) {
88
+ // Only conduct a search after fully mounting and entering a new non-empty pattern
89
+ setIsSearching(pattern.trim().length >= 1);
90
+
91
+ // Search about 2 seconds after entering a new pattern
92
+ const delaySearch = setTimeout(() => {
93
+ if (
94
+ pattern.trim().length >= 1 &&
95
+ inputRef.current
96
+ ) {
97
+ setSearchResults(shareDBDoc);
98
+ setIsSearching(false);
99
+ }
100
+ }, 2000);
101
+
102
+ return () => clearTimeout(delaySearch);
103
+ } else {
104
+ setIsMounted(true);
105
+ }
106
+ }, [pattern]);
107
+
108
+ return (
109
+ <div>
110
+ <Form.Group
111
+ className="sidebar-search-form mb-3"
112
+ controlId="searchName"
113
+ >
114
+ <Form.Control
115
+ type="text"
116
+ value={pattern}
117
+ onChange={(e) => setSearch(e.target.value)}
118
+ ref={inputRef}
119
+ spellCheck="false"
120
+ />
121
+ </Form.Group>
122
+ {Object.keys(results).length >= 1 &&
123
+ pattern.trim().length >= 1 ? (
124
+ <div className="search-results">
125
+ {Object.entries(results)
126
+ .filter(
127
+ ([_, file]) => file.visibility !== 'closed',
128
+ )
129
+ .map(([fileId, file]: [string, SearchFile]) => (
130
+ <div
131
+ className="search-result"
132
+ key={file.name}
133
+ >
134
+ <div className="search-file-heading">
135
+ <div className="search-file-title">
136
+ <div
137
+ className="arrow-wrapper"
138
+ style={{
139
+ transform: `rotate(${file.visibility === 'open' ? 90 : 0}deg)`,
140
+ }}
141
+ onClick={() => {
142
+ setSearchFileVisibility(
143
+ shareDBDoc,
144
+ fileId,
145
+ file.visibility === 'open'
146
+ ? 'flattened'
147
+ : 'open',
148
+ );
149
+ }}
150
+ >
151
+ <DirectoryArrowSVG />
152
+ </div>
153
+ <div className="search-file-name">
154
+ {getExtensionIcon(
155
+ file.name.split('.')[1],
156
+ )}
157
+ <h5>{file.name}</h5>
158
+ </div>
159
+ </div>
160
+ <div className="search-file-info">
161
+ <h6 className="search-file-count">
162
+ {file.matches.length}
163
+ </h6>
164
+ <div
165
+ className="search-file-close"
166
+ onClick={() => {
167
+ setSearchFileVisibility(
168
+ shareDBDoc,
169
+ fileId,
170
+ 'closed',
171
+ );
172
+ }}
173
+ >
174
+ <CloseSVG />
175
+ </div>
176
+ </div>
177
+ </div>
178
+ <div className="search-file-lines">
179
+ {file.visibility != 'flattened' &&
180
+ file.matches.map((match) => {
181
+ const before = match.text.substring(
182
+ 0,
183
+ match.index,
184
+ );
185
+ const hit = match.text.substring(
186
+ match.index,
187
+ match.index + pattern.length,
188
+ );
189
+ const after = match.text.substring(
190
+ match.index + pattern.length,
191
+ );
192
+
193
+ return (
194
+ <p
195
+ className="search-line"
196
+ key={
197
+ file.name +
198
+ ' - ' +
199
+ match.line +
200
+ ' - ' +
201
+ match.index
202
+ }
203
+ onClick={() => {
204
+ setActiveFileId(fileId);
205
+ openTab({
206
+ fileId: fileId,
207
+ isTransient: false,
208
+ });
209
+
210
+ if (editorCache.get(fileId)) {
211
+ jumpToPattern(
212
+ editorCache.get(fileId)
213
+ .editor,
214
+ pattern,
215
+ match.line,
216
+ match.index,
217
+ );
218
+ }
219
+ }}
220
+ >
221
+ {before}
222
+ <span className="search-pattern">
223
+ {hit}
224
+ </span>
225
+ {after}
226
+ </p>
227
+ );
228
+ })}
229
+ </div>
230
+ </div>
231
+ ))}
232
+ </div>
233
+ ) : (
234
+ <div className="search-results">
235
+ <h6>
236
+ {isSearching ? 'Searching...' : 'No Results'}
237
+ </h6>
238
+ </div>
239
+ )}
240
+ </div>
241
+ );
242
+ };