vzcode 0.71.0 → 0.72.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-HJAv0wn0.js"></script>
24
- <link rel="stylesheet" crossorigin href="/assets/index-B4YHcAhs.css">
23
+ <script type="module" crossorigin src="/assets/index-BfS1mzJK.js"></script>
24
+ <link rel="stylesheet" crossorigin href="/assets/index-CpIQ8AoQ.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": "0.71.0",
3
+ "version": "0.72.0",
4
4
  "description": "Multiplayer code editor system",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -66,12 +66,12 @@
66
66
  "@codemirror/autocomplete": "^6.12.0",
67
67
  "@codemirror/lang-css": "^6.2.1",
68
68
  "@codemirror/lang-html": "^6.4.8",
69
- "@codemirror/lang-javascript": "^6.2.1",
69
+ "@codemirror/lang-javascript": "^6.2.2",
70
70
  "@codemirror/lang-json": "^6.0.1",
71
71
  "@codemirror/lang-markdown": "^6.2.4",
72
- "@codemirror/state": "^6.4.0",
72
+ "@codemirror/state": "^6.4.1",
73
73
  "@codemirror/theme-one-dark": "^6.1.2",
74
- "@codemirror/view": "^6.24.0",
74
+ "@codemirror/view": "^6.24.1",
75
75
  "@lezer/highlight": "^1.2.0",
76
76
  "@replit/codemirror-indentation-markers": "^6.5.0",
77
77
  "@replit/codemirror-interact": "^6.3.0",
@@ -79,27 +79,27 @@
79
79
  "@replit/codemirror-vscode-keymap": "^6.0.2",
80
80
  "@teamwork/websocket-json-stream": "^2.0.0",
81
81
  "@typescript/vfs": "^1.5.0",
82
- "@uiw/codemirror-theme-abcdef": "^4.21.22",
83
- "@uiw/codemirror-theme-dracula": "^4.21.22",
84
- "@uiw/codemirror-theme-eclipse": "^4.21.22",
85
- "@uiw/codemirror-theme-github": "^4.21.22",
86
- "@uiw/codemirror-theme-material": "^4.21.22",
87
- "@uiw/codemirror-theme-nord": "^4.21.22",
88
- "@uiw/codemirror-theme-okaidia": "^4.21.22",
89
- "@uiw/codemirror-theme-xcode": "^4.21.22",
90
- "@uiw/codemirror-themes": "^4.21.22",
82
+ "@uiw/codemirror-theme-abcdef": "^4.21.24",
83
+ "@uiw/codemirror-theme-dracula": "^4.21.24",
84
+ "@uiw/codemirror-theme-eclipse": "^4.21.24",
85
+ "@uiw/codemirror-theme-github": "^4.21.24",
86
+ "@uiw/codemirror-theme-material": "^4.21.24",
87
+ "@uiw/codemirror-theme-nord": "^4.21.24",
88
+ "@uiw/codemirror-theme-okaidia": "^4.21.24",
89
+ "@uiw/codemirror-theme-xcode": "^4.21.24",
90
+ "@uiw/codemirror-themes": "^4.21.24",
91
91
  "body-parser": "^1.20.2",
92
92
  "codemirror": "^6.0.1",
93
93
  "codemirror-ot": "^4.2.0",
94
94
  "color-hash": "^2.0.2",
95
95
  "d3-array": "^3.2.4",
96
96
  "diff-match-patch": "^1.0.5",
97
- "dotenv": "^16.4.4",
97
+ "dotenv": "^16.4.5",
98
98
  "express": "^4.18.2",
99
99
  "ignore": "^5.3.1",
100
100
  "json0-ot-diff": "^1.1.2",
101
101
  "ngrok": "^4.3.3",
102
- "open": "^10.0.3",
102
+ "open": "^10.0.4",
103
103
  "openai": "^4.28.0",
104
104
  "prettier-plugin-svelte": "^3.2.1",
105
105
  "react": "^18.2.0",
@@ -108,18 +108,18 @@
108
108
  "react-router-dom": "^6.22.1",
109
109
  "sharedb": "^4.1.2",
110
110
  "sharedb-client-browser": "^4.4.0",
111
- "vizhub-ui": "^3.20.0",
111
+ "vizhub-ui": "^3.21.0",
112
112
  "ws": "^8.16.0"
113
113
  },
114
114
  "devDependencies": {
115
- "@types/react": "^18.2.56",
115
+ "@types/react": "^18.2.60",
116
116
  "@types/react-dom": "^18.2.19",
117
117
  "@vitejs/plugin-react": "^4.2.1",
118
118
  "concurrently": "^8.2.2",
119
119
  "prettier": "^3.2.5",
120
- "sass": "^1.71.0",
120
+ "sass": "^1.71.1",
121
121
  "typescript": "^5.3.3",
122
- "vite": "^5.1.3",
123
- "vitest": "^1.3.0"
122
+ "vite": "^5.1.4",
123
+ "vitest": "^1.3.1"
124
124
  }
125
125
  }
@@ -61,6 +61,7 @@ function App() {
61
61
  localPresence,
62
62
  docPresence,
63
63
  submitOperation,
64
+ connected,
64
65
  } = useShareDB({
65
66
  connection,
66
67
  });
@@ -87,6 +88,7 @@ function App() {
87
88
  prettierWorker={prettierWorker}
88
89
  typeScriptWorker={typeScriptWorker}
89
90
  initialUsername={initialUsername}
91
+ connected={connected}
90
92
  >
91
93
  <div className="app">
92
94
  <VZLeft />
@@ -1,3 +1,9 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap');
2
+ @import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@200..900&display=swap');
3
+ @import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap');
4
+ @import url('https://fonts.googleapis.com/css2?family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap');
5
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
6
+ @import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap');
1
7
  :root {
2
8
  // --vzcode-font-family: ui-monospace, SFMono-Regular,
3
9
  // 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace !important;
@@ -28,7 +28,18 @@ export const useShareDB = ({
28
28
  const [content, setContent] =
29
29
  useState<VZCodeContent | null>(null);
30
30
 
31
+ const [connected, setConnected] =
32
+ useState<boolean>(false);
31
33
  useEffect(() => {
34
+ // Listen for connection state changes
35
+ connection.on('connected', () => {
36
+ setConnected(true);
37
+ });
38
+
39
+ connection.on('disconnected', () => {
40
+ setConnected(false);
41
+ });
42
+
32
43
  // Since there is only ever a single document,
33
44
  // these things are pretty arbitrary.
34
45
  // * `collection` - the ShareDB collection to use
@@ -106,5 +117,6 @@ export const useShareDB = ({
106
117
  localPresence,
107
118
  docPresence,
108
119
  submitOperation,
120
+ connected,
109
121
  };
110
122
  };
@@ -43,4 +43,8 @@
43
43
  background-color: #0077cc;
44
44
  color: white;
45
45
  }
46
+
47
+ .cm-line {
48
+ font-family: var(--vzcode-font-family);
49
+ }
46
50
  }
@@ -0,0 +1,8 @@
1
+ export const fonts = [
2
+ 'Roboto Mono',
3
+ 'Inconsolata',
4
+ 'Source Code Pro',
5
+ 'Ubuntu Mono',
6
+ 'JetBrains Mono',
7
+ 'Fira Code',
8
+ ];
@@ -101,6 +101,8 @@ export type VZCodeContextValue = {
101
101
  null | (() => void)
102
102
  >;
103
103
  runCodeRef: React.MutableRefObject<null | (() => void)>;
104
+
105
+ connected: boolean;
104
106
  };
105
107
 
106
108
  export const VZCodeProvider = ({
@@ -115,6 +117,7 @@ export const VZCodeProvider = ({
115
117
  children,
116
118
  codeError = null,
117
119
  enableManualPretter = true,
120
+ connected,
118
121
  }: {
119
122
  content: VZCodeContent;
120
123
  shareDBDoc: ShareDBDoc<VZCodeContent>;
@@ -127,6 +130,7 @@ export const VZCodeProvider = ({
127
130
  children: React.ReactNode;
128
131
  codeError?: string | null;
129
132
  enableManualPretter?: boolean;
133
+ connected: boolean;
130
134
  }) => {
131
135
  // Auto-run Pretter after local changes.
132
136
  const {
@@ -315,6 +319,8 @@ export const VZCodeProvider = ({
315
319
  handleCreateFileClick,
316
320
  runPrettierRef,
317
321
  runCodeRef,
322
+
323
+ connected,
318
324
  };
319
325
 
320
326
  return (
@@ -1,7 +1,16 @@
1
- import { useCallback, useContext, useRef } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import { Button, Modal, Form } from './bootstrap';
3
- import { themes } from './themes';
9
+ import { ThemeLabel, themes } from './themes';
4
10
  import { VZCodeContext } from './VZCodeContext';
11
+ import { fonts } from './Fonts/fonts';
12
+
13
+ const fontSizes = ['16px', '18px', '20px', '24px'];
5
14
 
6
15
  export const VZSettings = ({
7
16
  enableUsernameField = true,
@@ -18,11 +27,51 @@ export const VZSettings = ({
18
27
  setUsername,
19
28
  } = useContext(VZCodeContext);
20
29
 
21
- const handleThemeChange = useCallback((event) => {
22
- const selectedValue = event.target.value;
23
- console.log(selectedValue);
24
- setTheme(selectedValue);
25
- }, []);
30
+ const handleThemeChange = useCallback(
31
+ (event: React.ChangeEvent<HTMLSelectElement>) => {
32
+ setTheme(event.target.value as ThemeLabel);
33
+ },
34
+ [],
35
+ );
36
+
37
+ // Track selected font and font size.
38
+ // TODO store these in local storage
39
+ const [selectedFont, setSelectedFont] =
40
+ useState('Roboto Mono');
41
+ const [selectedFontSize, setSelectedFontSize] =
42
+ useState('16px');
43
+
44
+ // Called when the user selects a different font
45
+ const handleFontChange = useCallback(
46
+ (event: React.ChangeEvent<HTMLSelectElement>) => {
47
+ setSelectedFont(event.target.value);
48
+ },
49
+ [],
50
+ );
51
+
52
+ // Called when the user selects a different font size
53
+ const handleFontSizeChange = (
54
+ event: React.ChangeEvent<HTMLSelectElement>,
55
+ ) => {
56
+ setSelectedFontSize(event.target.value);
57
+ };
58
+
59
+ useEffect(() => {
60
+ document.body.style.setProperty(
61
+ '--vzcode-font-family',
62
+ selectedFont,
63
+ );
64
+ }, [selectedFont]);
65
+
66
+ useEffect(() => {
67
+ // const fontSize = event.target.value;
68
+ // const root = document.documentElement;
69
+ // root.style.setProperty('--vzcode-font-size', fontSize);
70
+ document.body.style.setProperty(
71
+ '--vzcode-font-size',
72
+ selectedFontSize,
73
+ );
74
+ }, [selectedFontSize]);
26
75
 
27
76
  const usernameRef = useRef<HTMLInputElement>(null);
28
77
 
@@ -77,6 +126,46 @@ export const VZSettings = ({
77
126
  Select a color theme for the editor
78
127
  </Form.Text>
79
128
  </Form.Group>
129
+
130
+ <Form.Group className="mb-3" controlId="formFork">
131
+ <Form.Label>Font</Form.Label>
132
+
133
+ <select
134
+ className="form-select"
135
+ onChange={handleFontChange}
136
+ value={selectedFont}
137
+ >
138
+ {fonts.map((font) => (
139
+ <option key={font} value={font}>
140
+ {font}
141
+ </option>
142
+ ))}
143
+ </select>
144
+
145
+ <Form.Text className="text-muted">
146
+ Select font for the editor
147
+ </Form.Text>
148
+ </Form.Group>
149
+
150
+ <Form.Group className="mb-3" controlId="formFork">
151
+ <Form.Label>Font Size</Form.Label>
152
+
153
+ <select
154
+ className="form-select"
155
+ onChange={handleFontSizeChange}
156
+ value={selectedFontSize}
157
+ >
158
+ {fontSizes.map((size) => (
159
+ <option key={size} value={size}>
160
+ {size}
161
+ </option>
162
+ ))}
163
+ </select>
164
+
165
+ <Form.Text className="text-muted">
166
+ Select a font size for the editor
167
+ </Form.Text>
168
+ </Form.Group>
80
169
  </Modal.Body>
81
170
  <Modal.Footer>
82
171
  <Button variant="primary" onClick={closeSettings}>
@@ -17,7 +17,7 @@ import './styles.scss';
17
17
  // TODO turn this UI back on when we are actually detecting
18
18
  // the connection status.
19
19
  // See https://github.com/vizhub-core/vzcode/issues/456
20
- const enableConnectionStatus = false;
20
+ const enableConnectionStatus = true;
21
21
 
22
22
  export const VZSidebar = ({
23
23
  createFileTooltipText = 'New File',
@@ -39,6 +39,7 @@ export const VZSidebar = ({
39
39
  isDirectoryOpen,
40
40
  toggleDirectory,
41
41
  handleOpenCreateFileModal,
42
+ connected,
42
43
  } = useContext(VZCodeContext);
43
44
 
44
45
  const fileTree = useMemo(
@@ -174,10 +175,13 @@ export const VZSidebar = ({
174
175
 
175
176
  {enableConnectionStatus && (
176
177
  <div className="connection-status">
177
- Connection Status
178
+ {connected ? 'Connected' : 'Connection Lost'}
178
179
  <div className="connection">
179
- Saved
180
- <div className="saved" />
180
+ <div
181
+ className={`connection-status-indicator ${
182
+ connected ? 'connected' : 'disconnected'
183
+ }`}
184
+ />
181
185
  </div>
182
186
  </div>
183
187
  )}
@@ -131,18 +131,20 @@
131
131
  display: flex;
132
132
  justify-content: space-between;
133
133
  padding: 10px;
134
- }
134
+ font-size: 12px;
135
135
 
136
- .connection {
137
- display: flex;
138
- gap: 6px;
139
- align-items: center;
140
- }
136
+ .connection-status-indicator {
137
+ width: 16px;
138
+ height: 16px;
139
+ border-radius: 50%;
140
+
141
+ &.connected {
142
+ background-color: var(--vh-color-success-01);
143
+ }
141
144
 
142
- .saved {
143
- width: 16px;
144
- height: 16px;
145
- border-radius: 99px;
146
- background-color: #34eb52;
145
+ &.disconnected {
146
+ background-color: var(--vh-color-warning-01);
147
+ }
148
+ }
147
149
  }
148
150
  }
@@ -240,6 +240,11 @@ onmessage = async ({ data }) => {
240
240
  // of type '"test"' can't be used to index type '{}'."
241
241
  const LINT_ERROR_CODE_ANY_TYPE_KEYS = 7053;
242
242
 
243
+ // "Property 'id' does not exist on type { ... }"
244
+ // Happens on objects with dynamic keys.
245
+ // Not valid in TypeScript, but common in JavaScript.
246
+ const LINT_ERROR_CODE_NON_EXISTENT_PROPERTY = 2339;
247
+
243
248
  if (debug) {
244
249
  console.log(tsErrors);
245
250
  }
@@ -249,7 +254,9 @@ onmessage = async ({ data }) => {
249
254
  error.code !== LINT_ERROR_CODE_IMPORT &&
250
255
  error.code !== LINT_ERROR_CODE_ANY_PARAM &&
251
256
  error.code !== LINT_ERROR_CODE_ANY_TYPE &&
252
- error.code !== LINT_ERROR_CODE_ANY_TYPE_KEYS,
257
+ error.code !== LINT_ERROR_CODE_ANY_TYPE_KEYS &&
258
+ error.code !==
259
+ LINT_ERROR_CODE_NON_EXISTENT_PROPERTY,
253
260
  );
254
261
  }
255
262
  tsErrors = convertToCodeMirrorDiagnostic(tsErrors);