vzcode 2.0.0 → 2.3.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 (218) hide show
  1. package/dist/assets/{buildWorker-Dsx6rOdK.js → buildWorker-wLkQ0yz1.js} +64 -64
  2. package/dist/assets/{index-BM8tDh6M.css → index-BoFeK4GL.css} +1 -1
  3. package/dist/assets/{index-BgqNq-ww.js → index-DuUjtrt6.js} +107 -107
  4. package/dist/assets/{worker-BeBZGG1n.js → worker-DHxSPM7N.js} +78 -78
  5. package/dist/cli.js +113 -0
  6. package/dist/index.html +2 -2
  7. package/{src/ot.ts → dist/ot.js} +2 -14
  8. package/{src/randomId.ts → dist/randomId.js} +5 -6
  9. package/dist/runCode.js +20 -0
  10. package/dist/server/aiChatHandler/aiEditing.js +89 -0
  11. package/dist/server/aiChatHandler/chatOperations.js +360 -0
  12. package/dist/server/aiChatHandler/errorHandling.js +49 -0
  13. package/dist/server/aiChatHandler/index.js +112 -0
  14. package/dist/server/aiChatHandler/llmStreaming.js +284 -0
  15. package/dist/server/aiChatHandler/validation.js +19 -0
  16. package/dist/server/computeInitialDocument.js +146 -0
  17. package/{src/server/config.ts → dist/server/config.js} +4 -7
  18. package/{src/server/featureFlags.ts → dist/server/featureFlags.js} +0 -3
  19. package/dist/server/generateAIResponse.js +129 -0
  20. package/dist/server/handleAIAssist.js +39 -0
  21. package/dist/server/handleAICopilot.js +81 -0
  22. package/dist/server/index.js +297 -0
  23. package/dist/server/livekit.js +17 -0
  24. package/dist/server/prettier.js +90 -0
  25. package/{src/server/setupEnv.ts → dist/server/setupEnv.js} +1 -2
  26. package/dist/submitOperation.js +14 -0
  27. package/dist/types.js +1 -0
  28. package/dist/utils/fileDiff.js +66 -0
  29. package/package.json +23 -22
  30. package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +0 -42
  31. package/src/client/AIAssist/AIAssistWidget/index.tsx +0 -135
  32. package/src/client/AIAssist/AIAssistWidget/style.scss +0 -47
  33. package/src/client/AIAssist/Spinner.jsx +0 -76
  34. package/src/client/AIAssist/formatFile.ts +0 -27
  35. package/src/client/AIAssist/generateFilesContext.ts +0 -25
  36. package/src/client/AIAssist/index.ts +0 -2
  37. package/src/client/AIAssist/startAIAssist.ts +0 -95
  38. package/src/client/App/index.tsx +0 -153
  39. package/src/client/App/style.scss +0 -82
  40. package/src/client/App/usePending.ts +0 -51
  41. package/src/client/App/useShareDB.ts +0 -161
  42. package/src/client/CodeEditor/Copilot/index.ts +0 -74
  43. package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +0 -12
  44. package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +0 -68
  45. package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +0 -174
  46. package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +0 -79
  47. package/src/client/CodeEditor/InteractiveWidgets/index.ts +0 -44
  48. package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +0 -12
  49. package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +0 -20
  50. package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +0 -143
  51. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +0 -48
  52. package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +0 -12
  53. package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +0 -25
  54. package/src/client/CodeEditor/basicSetup.ts +0 -73
  55. package/src/client/CodeEditor/getOrCreateEditor.tsx +0 -615
  56. package/src/client/CodeEditor/index.tsx +0 -202
  57. package/src/client/CodeEditor/json1PresenceBroadcast.ts +0 -41
  58. package/src/client/CodeEditor/json1PresenceDisplay.ts +0 -350
  59. package/src/client/CodeEditor/rainbowBrackets.ts +0 -122
  60. package/src/client/CodeEditor/style.scss +0 -156
  61. package/src/client/CodeEditor/typescriptExtension/worker.ts +0 -32
  62. package/src/client/CodeErrorOverlay/index.tsx +0 -77
  63. package/src/client/CodeErrorOverlay/style.scss +0 -33
  64. package/src/client/Fonts/fonts.ts +0 -8
  65. package/src/client/Icons/AdjustmentSVG.tsx +0 -19
  66. package/src/client/Icons/BugSVG.tsx +0 -20
  67. package/src/client/Icons/CloseSVG.tsx +0 -19
  68. package/src/client/Icons/CssSVG.tsx +0 -16
  69. package/src/client/Icons/DirectoryArrowSVG.tsx +0 -19
  70. package/src/client/Icons/EditSVG.tsx +0 -19
  71. package/src/client/Icons/FileSVG.tsx +0 -19
  72. package/src/client/Icons/FolderSVG.tsx +0 -20
  73. package/src/client/Icons/GearSVG.tsx +0 -16
  74. package/src/client/Icons/HtmlSVG.tsx +0 -16
  75. package/src/client/Icons/JavaScriptSVG.tsx +0 -16
  76. package/src/client/Icons/JsonSVG.tsx +0 -16
  77. package/src/client/Icons/MarkdownSVG.tsx +0 -16
  78. package/src/client/Icons/MicSVG.tsx +0 -25
  79. package/src/client/Icons/NewSVG.tsx +0 -19
  80. package/src/client/Icons/PinSVG.tsx +0 -14
  81. package/src/client/Icons/PlaySVG.tsx +0 -16
  82. package/src/client/Icons/QuestionMarkSVG.tsx +0 -18
  83. package/src/client/Icons/ReactSVG.tsx +0 -16
  84. package/src/client/Icons/SearchSVG.tsx +0 -20
  85. package/src/client/Icons/SparklesSVG.tsx +0 -23
  86. package/src/client/Icons/SplitEditorSVG.tsx +0 -34
  87. package/src/client/Icons/StopSVG.tsx +0 -15
  88. package/src/client/Icons/SvelteSVG.tsx +0 -16
  89. package/src/client/Icons/TrashSVG.tsx +0 -19
  90. package/src/client/Icons/TypeScriptSVG.tsx +0 -16
  91. package/src/client/Icons/index.tsx +0 -24
  92. package/src/client/ImageViewer/index.tsx +0 -91
  93. package/src/client/ImageViewer/style.scss +0 -41
  94. package/src/client/PresenceNotifications/PresenceNotifications.test.ts +0 -134
  95. package/src/client/PresenceNotifications/index.tsx +0 -158
  96. package/src/client/PresenceNotifications/style.scss +0 -17
  97. package/src/client/RunCodeWidget/index.tsx +0 -117
  98. package/src/client/RunCodeWidget/style.scss +0 -24
  99. package/src/client/SplitPaneResizeContext.tsx +0 -159
  100. package/src/client/TabList/Tab.tsx +0 -73
  101. package/src/client/TabList/index.tsx +0 -35
  102. package/src/client/TabList/style.scss +0 -51
  103. package/src/client/VZCodeContext/index.tsx +0 -29
  104. package/src/client/VZCodeContext/types.ts +0 -249
  105. package/src/client/VZCodeContext/useVZCodeState.ts +0 -584
  106. package/src/client/VZKeyboardShortcutsDoc.tsx +0 -148
  107. package/src/client/VZLeft.tsx +0 -28
  108. package/src/client/VZMiddle.tsx +0 -172
  109. package/src/client/VZResizer/index.tsx +0 -128
  110. package/src/client/VZResizer/styles.scss +0 -33
  111. package/src/client/VZRight.tsx +0 -113
  112. package/src/client/VZSettings.tsx +0 -275
  113. package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -196
  114. package/src/client/VZSidebar/AIChat/DiffView.scss +0 -136
  115. package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -176
  116. package/src/client/VZSidebar/AIChat/Message.tsx +0 -143
  117. package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -205
  118. package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
  119. package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -156
  120. package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
  121. package/src/client/VZSidebar/AIChat/index.tsx +0 -273
  122. package/src/client/VZSidebar/AIChat/styles.scss +0 -627
  123. package/src/client/VZSidebar/CreateDirModal.tsx +0 -111
  124. package/src/client/VZSidebar/CreateFileModal.tsx +0 -111
  125. package/src/client/VZSidebar/DeleteConfirmationModal.tsx +0 -76
  126. package/src/client/VZSidebar/DirectoryListing.tsx +0 -89
  127. package/src/client/VZSidebar/EmptyState.tsx +0 -11
  128. package/src/client/VZSidebar/FileListing.tsx +0 -91
  129. package/src/client/VZSidebar/FileTypeIcon.tsx +0 -49
  130. package/src/client/VZSidebar/Item.tsx +0 -237
  131. package/src/client/VZSidebar/Listing.tsx +0 -47
  132. package/src/client/VZSidebar/Search.tsx +0 -527
  133. package/src/client/VZSidebar/VisualEditor.tsx +0 -295
  134. package/src/client/VZSidebar/VoiceChatModal.tsx +0 -121
  135. package/src/client/VZSidebar/aiCopyPaste.ts +0 -199
  136. package/src/client/VZSidebar/index.tsx +0 -728
  137. package/src/client/VZSidebar/styles.scss +0 -612
  138. package/src/client/VZSidebar/useDragAndDrop.tsx +0 -408
  139. package/src/client/bootstrap.ts +0 -26
  140. package/src/client/buildWorker.ts +0 -3
  141. package/src/client/featureFlags.ts +0 -8
  142. package/src/client/generateRequestId.ts +0 -6
  143. package/src/client/getFileTree.ts +0 -53
  144. package/src/client/index.ts +0 -19
  145. package/src/client/main.jsx +0 -10
  146. package/src/client/presenceColor.ts +0 -8
  147. package/src/client/shouldTriggerRun.ts +0 -31
  148. package/src/client/sortFileTree.ts +0 -21
  149. package/src/client/tabsSearchParameters.test.ts +0 -79
  150. package/src/client/tabsSearchParameters.ts +0 -137
  151. package/src/client/themes/index.ts +0 -7
  152. package/src/client/themes/themes.ts +0 -77
  153. package/src/client/themes/uiwImports.ts +0 -32
  154. package/src/client/themes/useDynamicTheme.ts +0 -29
  155. package/src/client/themes/vizhubTheme/colors.ts +0 -80
  156. package/src/client/themes/vizhubTheme/index.ts +0 -193
  157. package/src/client/useActions.ts +0 -288
  158. package/src/client/useESLint/index.ts +0 -72
  159. package/src/client/useESLint/worker.ts +0 -113
  160. package/src/client/useEditorCache.ts +0 -35
  161. package/src/client/useFileCRUD.ts +0 -228
  162. package/src/client/useKeyboardShortcuts.ts +0 -451
  163. package/src/client/useOpenDirectories.ts +0 -99
  164. package/src/client/usePresenceAutoFollow.ts +0 -85
  165. package/src/client/usePrettier/index.ts +0 -178
  166. package/src/client/usePrettier/worker.ts +0 -109
  167. package/src/client/useRunCode.tsx +0 -15
  168. package/src/client/useRuntimeError.ts +0 -32
  169. package/src/client/useSubmitOperation.ts +0 -15
  170. package/src/client/useURLSync.ts +0 -137
  171. package/src/client/usernameLocalStorage.ts +0 -43
  172. package/src/client/utils/fileExtension.ts +0 -10
  173. package/src/client/utils/isImageFile.ts +0 -12
  174. package/src/client/vzReducer/aiChatReducer.ts +0 -44
  175. package/src/client/vzReducer/closeTabReducer.test.ts +0 -205
  176. package/src/client/vzReducer/closeTabsReducer.ts +0 -96
  177. package/src/client/vzReducer/createInitialState.ts +0 -38
  178. package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +0 -9
  179. package/src/client/vzReducer/findPane.ts +0 -19
  180. package/src/client/vzReducer/index.ts +0 -250
  181. package/src/client/vzReducer/openTabReducer.test.ts +0 -127
  182. package/src/client/vzReducer/openTabReducer.ts +0 -74
  183. package/src/client/vzReducer/searchReducer.test.ts +0 -292
  184. package/src/client/vzReducer/searchReducer.ts +0 -181
  185. package/src/client/vzReducer/setActiveFileIdReducer.ts +0 -28
  186. package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +0 -76
  187. package/src/client/vzReducer/setIsDocOpenReducer.ts +0 -9
  188. package/src/client/vzReducer/setIsSettingsOpenReducer.ts +0 -9
  189. package/src/client/vzReducer/setThemeReducer.ts +0 -9
  190. package/src/client/vzReducer/setUsernameReducer.ts +0 -9
  191. package/src/client/vzReducer/splitCurrentPaneReducer.ts +0 -66
  192. package/src/client/vzReducer/toggleAutoFollowReducer.ts +0 -12
  193. package/src/client/vzReducer/updatePane.ts +0 -40
  194. package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +0 -30
  195. package/src/client/vzReducer/visualEditorReducer.ts +0 -9
  196. package/src/reactRouterExports.ts +0 -15
  197. package/src/runCode.ts +0 -27
  198. package/src/server/aiChatHandler/aiEditing.ts +0 -152
  199. package/src/server/aiChatHandler/chatOperations.ts +0 -510
  200. package/src/server/aiChatHandler/errorHandling.ts +0 -66
  201. package/src/server/aiChatHandler/index.ts +0 -200
  202. package/src/server/aiChatHandler/llmStreaming.ts +0 -419
  203. package/src/server/aiChatHandler/undoHandler.ts +0 -97
  204. package/src/server/aiChatHandler/validation.ts +0 -24
  205. package/src/server/computeInitialDocument.ts +0 -220
  206. package/src/server/generateAIResponse.ts +0 -188
  207. package/src/server/handleAIAssist.ts +0 -53
  208. package/src/server/handleAIChatUndo.ts +0 -2
  209. package/src/server/handleAICopilot.ts +0 -97
  210. package/src/server/index.ts +0 -388
  211. package/src/server/livekit.ts +0 -24
  212. package/src/server/prettier.ts +0 -115
  213. package/src/submitOperation.ts +0 -25
  214. package/src/types.ts +0 -205
  215. package/src/utils/fileDiff.ts +0 -117
  216. package/src/vite-env.d.ts +0 -10
  217. /package/{src/server/handleAIChatMessage.ts → dist/server/handleAIChatMessage.js} +0 -0
  218. /package/{src/server/isDirectory.ts → dist/server/isDirectory.js} +0 -0
@@ -1,111 +0,0 @@
1
- import {
2
- useState,
3
- useCallback,
4
- useRef,
5
- useEffect,
6
- useContext,
7
- } from 'react';
8
- import { Modal, Form, Button } from '../bootstrap';
9
- import { VZCodeContext } from '../VZCodeContext';
10
-
11
- export const CreateFileModal = ({
12
- initialFileName = '',
13
- }) => {
14
- const [newName, setNewName] = useState(initialFileName);
15
- const inputRef = useRef(null);
16
-
17
- const {
18
- files,
19
- isCreateFileModalOpen,
20
- handleCloseCreateFileModal,
21
- handleCreateFileClick,
22
- } = useContext(VZCodeContext);
23
-
24
- useEffect(() => {
25
- if (isCreateFileModalOpen && inputRef.current) {
26
- inputRef.current.focus();
27
- }
28
- }, [isCreateFileModalOpen]);
29
-
30
- const handleNameChange = useCallback((event) => {
31
- setNewName(event.target.value);
32
- }, []);
33
-
34
- const onCreateClick = useCallback(() => {
35
- handleCreateFileClick(newName);
36
- setNewName('');
37
- }, [newName, handleCreateFileClick]);
38
-
39
- // Returns true if file name is valid, false otherwise.
40
- const validateFileName = useCallback(
41
- (fileName: string) => {
42
- let valid;
43
- //General Character Check
44
- const regex =
45
- /^[a-zA-Z0-9](?:[a-zA-Z0-9 ./+=_-]*[a-zA-Z0-9])?$/;
46
- valid = regex.test(fileName);
47
-
48
- //Check for Duplicate Filename
49
- for (const key in files) {
50
- if (fileName === files[key].name) {
51
- valid = false;
52
- }
53
- }
54
-
55
- return valid;
56
- },
57
- [files],
58
- );
59
-
60
- const handleKeyDown = useCallback(
61
- (e) => {
62
- if (
63
- e.key === 'Enter' &&
64
- validateFileName(newName) &&
65
- (e.ctrlKey ||
66
- e.shiftKey ||
67
- (!e.altKey && !e.metaKey))
68
- ) {
69
- onCreateClick();
70
- }
71
- },
72
- [onCreateClick, validateFileName, newName],
73
- );
74
-
75
- return isCreateFileModalOpen ? (
76
- <Modal
77
- show={isCreateFileModalOpen}
78
- onHide={handleCloseCreateFileModal}
79
- animation={false}
80
- onKeyDown={handleKeyDown}
81
- >
82
- <Modal.Header closeButton>
83
- <Modal.Title>Create File</Modal.Title>
84
- </Modal.Header>
85
- <Modal.Body>
86
- <Form.Group className="mb-3" controlId="fileName">
87
- <Form.Label>File Name</Form.Label>
88
- <Form.Control
89
- type="text"
90
- value={newName}
91
- onChange={handleNameChange}
92
- ref={inputRef}
93
- spellCheck="false"
94
- />
95
- <Form.Text className="text-muted">
96
- Enter the name for your file
97
- </Form.Text>
98
- </Form.Group>
99
- </Modal.Body>
100
- <Modal.Footer>
101
- <Button
102
- variant="primary"
103
- onClick={onCreateClick}
104
- disabled={!validateFileName(newName)}
105
- >
106
- Create File
107
- </Button>
108
- </Modal.Footer>
109
- </Modal>
110
- ) : null;
111
- };
@@ -1,76 +0,0 @@
1
- import { Button, Modal } from '../bootstrap';
2
- import { useCallback, useEffect } from 'react';
3
-
4
- // Confirmation modal for deleting a file or directory.
5
- // Inspired by https://react-bootstrap.netlify.app/docs/components/modal/#live-demo
6
-
7
- export const DeleteConfirmationModal = ({
8
- show,
9
- onClose,
10
- onConfirm,
11
- isDirectory,
12
- name,
13
- }) => {
14
- const handleEnterKey = useCallback(
15
- (event: KeyboardEvent) => {
16
- if (event.key === 'Enter') {
17
- onConfirm();
18
- }
19
- },
20
- [onConfirm],
21
- );
22
-
23
- useEffect(() => {
24
- if (show) {
25
- window.addEventListener('keydown', handleEnterKey);
26
- } else {
27
- window.removeEventListener('keydown', handleEnterKey);
28
- }
29
-
30
- return () => {
31
- window.removeEventListener('keydown', handleEnterKey);
32
- };
33
- }, [show, handleEnterKey]);
34
-
35
- return (
36
- <Modal show={show} onHide={onClose} centered>
37
- <Modal.Header closeButton onClick={onClose}>
38
- <Modal.Title>
39
- Delete{' '}
40
- {name === 'all files'
41
- ? 'All Files'
42
- : isDirectory
43
- ? 'Directory'
44
- : 'File'}
45
- </Modal.Title>
46
- </Modal.Header>
47
-
48
- <Modal.Body>
49
- <p>
50
- {name === 'all files' ? (
51
- 'This will delete all files in the project.'
52
- ) : (
53
- <>
54
- This will delete the{' '}
55
- {isDirectory ? 'directory' : 'file'}{' '}
56
- <strong>{name}</strong>.
57
- </>
58
- )}
59
- </p>
60
- </Modal.Body>
61
-
62
- <Modal.Footer>
63
- <Button
64
- variant="secondary"
65
- type="button"
66
- onClick={onClose}
67
- >
68
- Cancel
69
- </Button>
70
- <Button variant="primary" onClick={onConfirm}>
71
- Delete
72
- </Button>
73
- </Modal.Footer>
74
- </Modal>
75
- );
76
- };
@@ -1,89 +0,0 @@
1
- import { useCallback, useContext, useMemo } from 'react';
2
- import type { FileTree, FileTreeFile } from '../../types';
3
- import { DirectoryArrowSVG } from '../Icons';
4
- import { VZCodeContext } from '../VZCodeContext';
5
- import { Item } from './Item';
6
- import { Listing } from './Listing';
7
-
8
- export const DirectoryListing = ({
9
- name,
10
- path,
11
- children,
12
- handleFileClick,
13
- handleFileDoubleClick,
14
- }: {
15
- name: string;
16
- path: string;
17
- children: Array<FileTree | FileTreeFile>;
18
- handleFileClick: (fileId: string) => void;
19
- handleFileDoubleClick: (fileId: string) => void;
20
- }) => {
21
- const {
22
- renameDirectory,
23
- deleteDirectory,
24
- isDirectoryOpen,
25
- toggleDirectory,
26
- sidebarPresenceIndicators,
27
- } = useContext(VZCodeContext);
28
-
29
- const handleClick = useCallback(() => {
30
- toggleDirectory(path);
31
- }, [toggleDirectory, path]);
32
-
33
- const handleDeleteClick = useCallback(() => {
34
- deleteDirectory(path);
35
- }, [deleteDirectory, path]);
36
-
37
- const handleRenameClick = useCallback(
38
- (newName: string) => {
39
- renameDirectory(path, name, newName);
40
- },
41
- [renameDirectory, path, name],
42
- );
43
-
44
- const isOpen = useMemo(
45
- () => isDirectoryOpen(path),
46
- [isDirectoryOpen, path],
47
- );
48
-
49
- return (
50
- <>
51
- <Item
52
- id={path}
53
- name={name}
54
- handleClick={handleClick}
55
- handleDeleteClick={handleDeleteClick}
56
- handleRenameClick={handleRenameClick}
57
- isDirectory={true}
58
- >
59
- <div
60
- className="arrow-wrapper"
61
- style={{
62
- transform: `rotate(${isOpen ? 90 : 0}deg)`,
63
- }}
64
- >
65
- <DirectoryArrowSVG />
66
- </div>
67
- <div className="name">{name}</div>
68
- </Item>
69
- {children && isOpen ? (
70
- <div className="indentation">
71
- {children.map((entity) => {
72
- const { fileId } = entity as FileTreeFile;
73
- const { path } = entity as FileTree;
74
- return (
75
- <Listing
76
- entity={entity}
77
- key={fileId || path}
78
- handleFileClick={handleFileClick}
79
- handleFileDoubleClick={
80
- handleFileDoubleClick
81
- }
82
- />
83
- );
84
- })}
85
- </div>
86
- ) : null}
87
- </>
88
- );
89
- };
@@ -1,11 +0,0 @@
1
- import React from 'react';
2
-
3
- interface EmptyStateProps {
4
- children: React.ReactNode;
5
- }
6
-
7
- export const EmptyState: React.FC<EmptyStateProps> = ({
8
- children,
9
- }) => {
10
- return <div className="empty-state">{children}</div>;
11
- };
@@ -1,91 +0,0 @@
1
- import { useCallback, useContext } from 'react';
2
- import { Item } from './Item';
3
- import { PresenceIndicator } from '../../types';
4
- import { VizFileId } from '@vizhub/viz-types';
5
- import { VZCodeContext } from '../VZCodeContext';
6
- import { FileTypeIcon } from './FileTypeIcon';
7
- import { assignUserColor } from '../presenceColor';
8
-
9
- const PresenceIndicators = ({
10
- presence,
11
- }: {
12
- presence: PresenceIndicator[];
13
- }) => {
14
- return (
15
- <div className="presence-indicators">
16
- {presence.map((indicator, index) => {
17
- // Get the raw RGB values from assignUserColor
18
- const color = assignUserColor(indicator.username);
19
-
20
- // Format it as `rgb()` directly in the component
21
- const formattedColor = `rgb(${color})`;
22
-
23
- //console.log(`Username: ${indicator.username}, Assigned Color: ${formattedColor}`);
24
-
25
- return (
26
- <div
27
- key={index}
28
- className="presence-indicator"
29
- style={{ backgroundColor: formattedColor }}
30
- >
31
- {indicator.username[0]}
32
- </div>
33
- );
34
- })}
35
- </div>
36
- );
37
- };
38
-
39
- export const FileListing = ({
40
- name,
41
- fileId,
42
- handleFileClick,
43
- handleFileDoubleClick,
44
- isActive,
45
- presence,
46
- }: {
47
- name: string;
48
- fileId: VizFileId;
49
- handleFileClick: (fileId: VizFileId) => void;
50
- handleFileDoubleClick: (fileId: VizFileId) => void;
51
- isActive: boolean;
52
- presence: PresenceIndicator[];
53
- }) => {
54
- const { renameFile, deleteFile } =
55
- useContext(VZCodeContext);
56
-
57
- const handleClick = useCallback(() => {
58
- handleFileClick(fileId);
59
- }, [fileId, handleFileClick]);
60
-
61
- const handleDoubleClick = useCallback(() => {
62
- handleFileDoubleClick(fileId);
63
- }, [fileId, handleFileDoubleClick]);
64
-
65
- const handleDeleteClick = useCallback(() => {
66
- deleteFile(fileId);
67
- }, [fileId, deleteFile]);
68
-
69
- const handleRenameClick = useCallback(
70
- (newName: string) => {
71
- renameFile(fileId, newName);
72
- },
73
- [fileId, renameFile],
74
- );
75
-
76
- return (
77
- <Item
78
- id={fileId}
79
- name={name}
80
- handleClick={handleClick}
81
- handleDoubleClick={handleDoubleClick}
82
- handleDeleteClick={handleDeleteClick}
83
- handleRenameClick={handleRenameClick}
84
- isActive={isActive}
85
- >
86
- <PresenceIndicators presence={presence} />
87
- <FileTypeIcon name={name} />
88
- {name}
89
- </Item>
90
- );
91
- };
@@ -1,49 +0,0 @@
1
- import { useMemo } from 'react';
2
- import {
3
- FileSVG,
4
- JavaScriptSVG,
5
- TypeScriptSVG,
6
- ReactSVG,
7
- SvelteSVG,
8
- JsonSVG,
9
- MarkdownSVG,
10
- HtmlSVG,
11
- CssSVG,
12
- } from '../Icons';
13
-
14
- export function getExtensionIcon(fileName: string) {
15
- const extension = fileName.split('.');
16
-
17
- switch (extension[extension.length - 1]) {
18
- case 'jsx':
19
- case 'tsx':
20
- return <ReactSVG />;
21
- case 'js':
22
- return <JavaScriptSVG />;
23
- case 'ts':
24
- return <TypeScriptSVG />;
25
- case 'json':
26
- return <JsonSVG />;
27
- case 'md':
28
- return <MarkdownSVG />;
29
- case 'html':
30
- return <HtmlSVG />;
31
- case 'css':
32
- return <CssSVG />;
33
- case 'svelte':
34
- return <SvelteSVG />;
35
- default:
36
- return <FileSVG />;
37
- }
38
- }
39
-
40
- // Various neat icons based on the file extension
41
- export const FileTypeIcon = ({
42
- name,
43
- }: {
44
- name: string;
45
- }) => (
46
- <i className="file-icon">
47
- {useMemo(() => getExtensionIcon(name), [name])}
48
- </i>
49
- );
@@ -1,237 +0,0 @@
1
- import {
2
- useState,
3
- useCallback,
4
- useRef,
5
- useEffect,
6
- useContext,
7
- } from 'react';
8
- import { ItemId } from '../../types';
9
- import { EditSVG, TrashSVG } from '../Icons';
10
- import { Tooltip, OverlayTrigger } from '../bootstrap';
11
- import { VZCodeContext } from '../VZCodeContext';
12
- import { FileTypeIcon } from './FileTypeIcon';
13
-
14
- // TODO consider moving this up to a higher level of the component tree
15
- import { DeleteConfirmationModal } from './DeleteConfirmationModal';
16
-
17
- const enableRenameDirectory = true;
18
-
19
- // A file or directory in the sidebar.
20
- export const Item = ({
21
- id,
22
- name,
23
- children,
24
- handleClick,
25
- handleDoubleClick,
26
- handleRenameClick,
27
- handleDeleteClick,
28
- isDirectory = false,
29
- isActive = false,
30
- renameFileTooltipText = isDirectory
31
- ? 'Rename Directory'
32
- : 'Rename File',
33
- deleteFileTooltipText = isDirectory
34
- ? 'Delete Directory'
35
- : 'Delete File',
36
- }: {
37
- id: ItemId;
38
- name: string;
39
- children: React.ReactNode;
40
- handleClick: (event: React.MouseEvent) => void;
41
- handleDoubleClick?: (event: React.MouseEvent) => void;
42
- handleRenameClick: (newName: string) => void;
43
- handleDeleteClick: () => void;
44
- isDirectory?: boolean;
45
- isActive?: boolean;
46
- renameFileTooltipText?: string;
47
- deleteFileTooltipText?: string;
48
- }) => {
49
- const { hoveredItemId, setHoveredItemId } =
50
- useContext(VZCodeContext);
51
- // // Tracks whether the mouse is hovering over the file or directory
52
- // const [isHovered, setIsHovered] = useState(false);
53
- const isHovered = hoveredItemId === id;
54
- const setIsHovered = useCallback(
55
- (isHovered: boolean) => {
56
- if (isHovered) {
57
- setHoveredItemId(id);
58
- } else {
59
- setHoveredItemId(null);
60
- }
61
- },
62
- [id, setHoveredItemId],
63
- );
64
-
65
- // Tracks whether the file is being renamed (inline text input)
66
- const [isRenaming, setIsRenaming] = useState(false);
67
-
68
- // Tracks the value of the input field when renaming
69
- const [renameValue, setRenameValue] = useState('');
70
-
71
- // Tracks whether the delete confirmation modal is open
72
- const [showModal, setShowModal] = useState(false);
73
-
74
- // Ref to track the input DOM, so that we can focus and blur it
75
- const renameInputRef = useRef(null);
76
-
77
- const onKeyDown = useCallback(
78
- (event: React.KeyboardEvent<HTMLInputElement>) => {
79
- if (event.key === 'Escape') {
80
- setIsRenaming(false);
81
- } else if (event.key === 'Enter') {
82
- renameInputRef.current.blur();
83
- }
84
- },
85
- [],
86
- );
87
-
88
- const onBlur = useCallback(() => {
89
- setIsRenaming(false);
90
- if (renameInputRef.current.value.trim() === '') {
91
- // Renaming to empty signals deletion
92
- setShowModal(true);
93
- } else {
94
- handleRenameClick(renameInputRef.current.value);
95
- }
96
- }, [handleRenameClick]);
97
-
98
- const handleRenameIconClick = useCallback(
99
- (event: React.MouseEvent) => {
100
- event.stopPropagation();
101
- setIsRenaming(!isRenaming);
102
- setRenameValue(name);
103
- },
104
- [name, isRenaming],
105
- );
106
-
107
- // Focus the input field when renaming
108
- useEffect(() => {
109
- if (isRenaming) {
110
- renameInputRef.current.focus();
111
- }
112
- }, [isRenaming]);
113
-
114
- // Function to open the delete file confirmation modal
115
- const handleModalOpen = useCallback(
116
- (event: React.MouseEvent) => {
117
- event.stopPropagation();
118
- setShowModal(true);
119
- },
120
- [],
121
- );
122
-
123
- // Function to close the modal
124
- const handleModalClose = useCallback(() => {
125
- setShowModal(false);
126
- }, []);
127
-
128
- // Function to handle confirmation on modal
129
- const handleConfirmModal = useCallback(
130
- (event: React.MouseEvent | undefined) => {
131
- // TODO clean this up.
132
- // This was added to prevent parent listeners from firing
133
- // when the modal is confirmed.
134
- event?.stopPropagation();
135
- setShowModal(false);
136
- handleDeleteClick();
137
- },
138
- [handleDeleteClick],
139
- );
140
-
141
- const handleMouseEnter = useCallback(() => {
142
- setIsHovered(true);
143
- }, []);
144
-
145
- const handleMouseLeave = useCallback(() => {
146
- setIsHovered(false);
147
- }, []);
148
-
149
- const onChange = useCallback(() => {
150
- setRenameValue(renameInputRef.current.value);
151
- }, []);
152
-
153
- return (
154
- <div
155
- className={`file-or-directory user-select-none ${
156
- isActive ? 'active-file' : ''
157
- }`}
158
- onClick={isRenaming ? null : handleClick}
159
- onDoubleClick={
160
- isRenaming || !handleDoubleClick
161
- ? null
162
- : handleDoubleClick
163
- }
164
- onMouseEnter={handleMouseEnter}
165
- onMouseLeave={handleMouseLeave}
166
- >
167
- <div className="name">
168
- {isRenaming ? (
169
- <>
170
- <FileTypeIcon name={renameValue} />
171
- <input
172
- className="rename-input"
173
- ref={renameInputRef}
174
- type="text"
175
- aria-label="Field name"
176
- value={renameValue}
177
- onKeyDown={onKeyDown}
178
- onBlur={onBlur}
179
- onChange={onChange}
180
- />
181
- </>
182
- ) : (
183
- children
184
- )}
185
- </div>
186
- {isHovered && !isRenaming ? (
187
- <div
188
- className="utils"
189
- style={{ position: 'relative' }}
190
- >
191
- {(isDirectory ? enableRenameDirectory : true) ? (
192
- <OverlayTrigger
193
- placement="top"
194
- overlay={
195
- <Tooltip id="rename-file-tooltip">
196
- {renameFileTooltipText}
197
- </Tooltip>
198
- }
199
- >
200
- <i
201
- onClick={handleRenameIconClick}
202
- className="icon-button icon-button-dark"
203
- >
204
- <EditSVG />
205
- </i>
206
- </OverlayTrigger>
207
- ) : null}
208
- <OverlayTrigger
209
- placement="top"
210
- overlay={
211
- <Tooltip id="delete-file-tooltip">
212
- {deleteFileTooltipText}
213
- </Tooltip>
214
- }
215
- >
216
- <i
217
- onClick={handleModalOpen}
218
- className="icon-button icon-button-dark"
219
- >
220
- <TrashSVG />
221
- </i>
222
- </OverlayTrigger>
223
- </div>
224
- ) : null}
225
- {/* TODO Move this up to a higher level of the tree */}
226
- {showModal && (
227
- <DeleteConfirmationModal
228
- show={showModal}
229
- onClose={handleModalClose}
230
- onConfirm={handleConfirmModal}
231
- isDirectory={isDirectory}
232
- name={name}
233
- />
234
- )}
235
- </div>
236
- );
237
- };
@@ -1,47 +0,0 @@
1
- import { useContext } from 'react';
2
- import { VizFileId } from '@vizhub/viz-types';
3
- import type { FileTree, FileTreeFile } from '../../types';
4
- import { VZCodeContext } from '../VZCodeContext';
5
- import { DirectoryListing } from './DirectoryListing';
6
- import { FileListing } from './FileListing';
7
-
8
- // A "Listing" is a "FileListing" or a "DirectoryListing"
9
- // that appears in the Sidebar.
10
- export const Listing = ({
11
- entity,
12
- handleFileClick,
13
- handleFileDoubleClick,
14
- }: {
15
- entity: FileTree | FileTreeFile;
16
- handleFileClick: (fileId: VizFileId) => void;
17
- handleFileDoubleClick: (fileId: VizFileId) => void;
18
- }) => {
19
- const { activePane, sidebarPresenceIndicators } =
20
- useContext(VZCodeContext);
21
- const { name, file, fileId } = entity as FileTreeFile;
22
- const { path, children } = entity as FileTree;
23
-
24
- const presence =
25
- sidebarPresenceIndicators?.filter(
26
- (indicator) => indicator.fileId === fileId,
27
- ) || [];
28
-
29
- return file ? (
30
- <FileListing
31
- fileId={fileId}
32
- name={name}
33
- handleFileClick={handleFileClick}
34
- handleFileDoubleClick={handleFileDoubleClick}
35
- isActive={fileId === activePane.activeFileId}
36
- presence={presence}
37
- />
38
- ) : (
39
- <DirectoryListing
40
- name={name}
41
- path={path}
42
- children={children}
43
- handleFileClick={handleFileClick}
44
- handleFileDoubleClick={handleFileDoubleClick}
45
- />
46
- );
47
- };