vzcode 2.15.0 → 2.16.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.
Files changed (45) hide show
  1. package/dist/assets/{index-BpUpNto4.js → index-C2BLPyQP.js} +138 -125
  2. package/dist/assets/{index-DLm5FQ0E.css → index-DVR90LwF.css} +1 -1
  3. package/dist/index.html +2 -2
  4. package/dist/server/aiChatHandler/chatOperations.js +168 -35
  5. package/dist/server/aiChatHandler/index.js +11 -30
  6. package/dist/server/aiChatHandler/llmStreaming.js +105 -118
  7. package/package.json +11 -11
  8. package/src/client/AIAssist/AIAssistWidget/index.tsx +12 -1
  9. package/src/client/App/useShareDB.ts +1 -1
  10. package/src/client/CodeEditor/index.tsx +9 -10
  11. package/src/client/VZCodeContext/types.ts +3 -1
  12. package/src/client/VZCodeContext/useVZCodeState.ts +7 -5
  13. package/src/client/VZRight.tsx +10 -2
  14. package/src/client/VZSidebar/AIChat/ChatInput.tsx +1 -7
  15. package/src/client/VZSidebar/AIChat/DiffView.scss +1 -0
  16. package/src/client/VZSidebar/AIChat/DiffView.tsx +72 -29
  17. package/src/client/VZSidebar/AIChat/FileEditingIndicator.tsx +81 -0
  18. package/src/client/VZSidebar/AIChat/IndividualFileDiff.tsx +86 -0
  19. package/src/client/VZSidebar/AIChat/JumpToLatestButton.tsx +64 -0
  20. package/src/client/VZSidebar/AIChat/Message.tsx +68 -53
  21. package/src/client/VZSidebar/AIChat/MessageList.tsx +139 -118
  22. package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +63 -21
  23. package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +4 -118
  24. package/src/client/VZSidebar/AIChat/index.tsx +62 -19
  25. package/src/client/VZSidebar/AIChat/styles.scss +159 -16
  26. package/src/client/VZSidebar/Item.tsx +2 -2
  27. package/src/client/VZSidebar/Search.tsx +13 -6
  28. package/src/client/VZSidebar/VisualEditor/VisualEditor.tsx +39 -23
  29. package/src/client/VZSidebar/VisualEditor/utils.ts +1 -1
  30. package/src/client/VZSidebar/index.tsx +12 -10
  31. package/src/client/VZSidebar/useDragAndDrop.tsx +225 -214
  32. package/src/client/featureFlags.ts +3 -0
  33. package/src/client/hooks/useAutoScroll.ts +329 -0
  34. package/src/client/tabsSearchParameters.ts +1 -17
  35. package/src/client/useFileCRUD.ts +5 -2
  36. package/src/client/useKeyboardShortcuts.ts +7 -0
  37. package/src/client/useOpenDirectories.ts +2 -1
  38. package/src/client/usePrettier/index.ts +1 -1
  39. package/src/client/useURLSync.ts +1 -0
  40. package/src/client/utils/scrollUtils.ts +170 -0
  41. package/src/client/vzReducer/searchReducer.ts +6 -3
  42. package/src/server/aiChatHandler/chatOperations.ts +224 -43
  43. package/src/server/aiChatHandler/index.ts +8 -48
  44. package/src/server/aiChatHandler/llmStreaming.ts +149 -170
  45. package/src/types.ts +81 -1
@@ -32,21 +32,26 @@ export const VisualEditor = () => {
32
32
  >(null);
33
33
 
34
34
  let configFileId: VizFileId | null = null;
35
- for (const fileId in files) {
36
- if (files[fileId].name === CONFIG_FILE_NAME) {
37
- configFileId = fileId;
38
- break;
35
+ if (files) {
36
+ for (const fileId in files) {
37
+ if (files[fileId].name === CONFIG_FILE_NAME) {
38
+ configFileId = fileId;
39
+ break;
40
+ }
39
41
  }
40
42
  }
41
43
 
42
44
  const configData = useMemo(() => {
45
+ if (!files || !configFileId) {
46
+ return null;
47
+ }
43
48
  try {
44
49
  return JSON.parse(files[configFileId].text);
45
50
  } catch (_error) {
46
51
  console.error('Error parsing config.json:', _error);
47
52
  return null;
48
53
  }
49
- }, [files?.[configFileId]?.text]);
54
+ }, [configFileId, files]);
50
55
 
51
56
  const onSliderChange = useCallback(
52
57
  (property: string) =>
@@ -78,7 +83,7 @@ export const VisualEditor = () => {
78
83
  },
79
84
  }));
80
85
  },
81
- [configData, files, configFileId, setLocalValues],
86
+ [configData, files, configFileId, submitOperation],
82
87
  );
83
88
 
84
89
  const onCheckboxChange = useCallback(
@@ -109,7 +114,7 @@ export const VisualEditor = () => {
109
114
  },
110
115
  }));
111
116
  },
112
- [configData, files, configFileId, setLocalValues],
117
+ [configData, files, configFileId, submitOperation],
113
118
  );
114
119
 
115
120
  const onTextInputChange = useCallback(
@@ -140,7 +145,7 @@ export const VisualEditor = () => {
140
145
  },
141
146
  }));
142
147
  },
143
- [configData, files, configFileId, setLocalValues],
148
+ [configData, files, configFileId, submitOperation],
144
149
  );
145
150
 
146
151
  const onDropdownChange = useCallback(
@@ -168,7 +173,7 @@ export const VisualEditor = () => {
168
173
  },
169
174
  }));
170
175
  },
171
- [configData, files, configFileId, setLocalValues],
176
+ [configData, files, configFileId, submitOperation],
172
177
  );
173
178
 
174
179
  // Custom dropdown handlers
@@ -228,12 +233,12 @@ export const VisualEditor = () => {
228
233
  try {
229
234
  const rgbColor = rgb(currentHex);
230
235
  hclFromRGB = hcl(rgbColor);
231
- } catch (error) {
236
+ } catch {
232
237
  // Fallback to black if conversion fails
233
238
  hclFromRGB = hcl('black');
234
239
  }
235
240
 
236
- let hclArray: number[] = [
241
+ const hclArray: number[] = [
237
242
  (localValues[`${property}_h`] as number) ??
238
243
  hclFromRGB.h,
239
244
  (localValues[`${property}_c`] as number) ??
@@ -262,7 +267,7 @@ export const VisualEditor = () => {
262
267
  } else {
263
268
  newHex = currentHex;
264
269
  }
265
- } catch (error) {
270
+ } catch {
266
271
  // Fallback to current color if conversion fails
267
272
  newHex = currentHex;
268
273
  }
@@ -293,11 +298,20 @@ export const VisualEditor = () => {
293
298
  },
294
299
  }));
295
300
  },
296
- [configData, files, configFileId, setLocalValues],
301
+ [
302
+ configData,
303
+ files,
304
+ configFileId,
305
+ submitOperation,
306
+ localValues,
307
+ ],
297
308
  );
298
309
 
299
310
  const visualEditorWidgets: VisualEditorConfigEntry[] =
300
- configData?.visualEditorWidgets ?? [];
311
+ useMemo(
312
+ () => configData?.visualEditorWidgets ?? [],
313
+ [configData],
314
+ );
301
315
 
302
316
  // Sync local values with config data when it changes (including remote updates)
303
317
  useEffect(() => {
@@ -335,7 +349,7 @@ export const VisualEditor = () => {
335
349
  lch.c;
336
350
  newLocalValues[`${widget.property}_l`] =
337
351
  lch.l;
338
- } catch (error) {
352
+ } catch {
339
353
  // Fallback values if conversion fails
340
354
  newLocalValues[`${widget.property}_l`] = 0;
341
355
  newLocalValues[`${widget.property}_c`] = 0;
@@ -346,7 +360,7 @@ export const VisualEditor = () => {
346
360
  }
347
361
  });
348
362
  setLocalValues(newLocalValues);
349
- }, [configData]);
363
+ }, [configData, localValues, visualEditorWidgets]);
350
364
 
351
365
  if (configFileId === null) {
352
366
  return (
@@ -372,8 +386,9 @@ export const VisualEditor = () => {
372
386
  return (
373
387
  <EmptyState>
374
388
  To begin using the visual editor, make sure your
375
- config.json has a key called "visualEditorWidgets",
376
- whose value is the config for the visual editor.
389
+ config.json has a key called
390
+ &quot;visualEditorWidgets&quot;, whose value is the
391
+ config for the visual editor.
377
392
  </EmptyState>
378
393
  );
379
394
  }
@@ -384,10 +399,11 @@ export const VisualEditor = () => {
384
399
  ) {
385
400
  return (
386
401
  <EmptyState>
387
- Your config.json file has "visualEditorWidgets" but
388
- it is not an array. Please make sure
389
- "visualEditorWidgets" is an array of widget
390
- configurations.
402
+ Your config.json file has
403
+ &quot;visualEditorWidgets&quot; but it is not an
404
+ array. Please make sure
405
+ &quot;visualEditorWidgets&quot; is an array of
406
+ widget configurations.
391
407
  </EmptyState>
392
408
  );
393
409
  }
@@ -488,7 +504,7 @@ export const VisualEditor = () => {
488
504
  try {
489
505
  const rgbColor = color(currentHex);
490
506
  hclColor = hcl(rgbColor);
491
- } catch (error) {
507
+ } catch {
492
508
  hclColor = hcl('black');
493
509
  }
494
510
 
@@ -31,7 +31,7 @@ export const hclOk = (
31
31
  try {
32
32
  const color = hcl(h, c, l);
33
33
  return color.displayable();
34
- } catch (e) {
34
+ } catch {
35
35
  return false;
36
36
  }
37
37
  };
@@ -167,10 +167,10 @@ export const VZSidebar = ({
167
167
  );
168
168
  const handleQuestionMarkClick = useCallback(() => {
169
169
  setIsDocOpen(true);
170
- }, []);
170
+ }, [setIsDocOpen]);
171
171
  const handleSettingsClick = useCallback(() => {
172
172
  setIsSettingsOpen(true);
173
- }, []);
173
+ }, [setIsSettingsOpen]);
174
174
 
175
175
  // State for AI operation feedback
176
176
  const [copyButtonText, setCopyButtonText] =
@@ -253,7 +253,7 @@ export const VZSidebar = ({
253
253
  // so that they can be displayed in the sidebar.
254
254
  useEffect(() => {
255
255
  docPresence;
256
- }, []);
256
+ }, [docPresence]);
257
257
 
258
258
  // Track the presence indicators for display in sidebar
259
259
  useEffect(() => {
@@ -281,7 +281,7 @@ export const VZSidebar = ({
281
281
  docPresence.off('receive', handleReceive);
282
282
  };
283
283
  }
284
- }, [docPresence]);
284
+ }, [docPresence, updatePresenceIndicator]);
285
285
 
286
286
  const [saved, setSaved] = useState(false);
287
287
  const [isConnecting, setIsConnecting] = useState(true);
@@ -579,9 +579,10 @@ export const VZSidebar = ({
579
579
  {isDragOver ? (
580
580
  <div className="empty drag-over">
581
581
  <div className="empty-text">
582
- It looks like you don't have any files
583
- yet! Click the "Create file" button
584
- above to create your first file.
582
+ It looks like you don&apos;t have any
583
+ files yet! Click the &quot;Create
584
+ file&quot; button above to create your
585
+ first file.
585
586
  </div>
586
587
  <div className="empty-text">
587
588
  Drop files here!
@@ -606,9 +607,10 @@ export const VZSidebar = ({
606
607
  ) : (
607
608
  <div className="empty">
608
609
  <div className="empty-text">
609
- It looks like you don't have any files
610
- yet! Click the "Create file" button
611
- above to create your first file.
610
+ It looks like you don&apos;t have any
611
+ files yet! Click the &quot;Create
612
+ file&quot; button above to create your
613
+ first file.
612
614
  </div>
613
615
  <div className="empty-text">
614
616
  Drop files here!