vzcode 2.2.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 (220) 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-CpxqGhXj.js → index-DuUjtrt6.js} +150 -150
  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 +22 -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/MicOffSVG.tsx +0 -35
  79. package/src/client/Icons/MicSVG.tsx +0 -25
  80. package/src/client/Icons/NewSVG.tsx +0 -19
  81. package/src/client/Icons/PinSVG.tsx +0 -14
  82. package/src/client/Icons/PlaySVG.tsx +0 -16
  83. package/src/client/Icons/QuestionMarkSVG.tsx +0 -18
  84. package/src/client/Icons/ReactSVG.tsx +0 -16
  85. package/src/client/Icons/SearchSVG.tsx +0 -20
  86. package/src/client/Icons/SparklesSVG.tsx +0 -23
  87. package/src/client/Icons/SplitEditorSVG.tsx +0 -34
  88. package/src/client/Icons/StopSVG.tsx +0 -15
  89. package/src/client/Icons/SvelteSVG.tsx +0 -16
  90. package/src/client/Icons/TrashSVG.tsx +0 -19
  91. package/src/client/Icons/TypeScriptSVG.tsx +0 -16
  92. package/src/client/Icons/index.tsx +0 -26
  93. package/src/client/ImageViewer/index.tsx +0 -91
  94. package/src/client/ImageViewer/style.scss +0 -41
  95. package/src/client/PresenceNotifications/PresenceNotifications.test.ts +0 -134
  96. package/src/client/PresenceNotifications/index.tsx +0 -158
  97. package/src/client/PresenceNotifications/style.scss +0 -17
  98. package/src/client/RunCodeWidget/index.tsx +0 -117
  99. package/src/client/RunCodeWidget/style.scss +0 -24
  100. package/src/client/SplitPaneResizeContext.tsx +0 -159
  101. package/src/client/TabList/Tab.tsx +0 -73
  102. package/src/client/TabList/index.tsx +0 -35
  103. package/src/client/TabList/style.scss +0 -51
  104. package/src/client/VZCodeContext/index.tsx +0 -29
  105. package/src/client/VZCodeContext/types.ts +0 -249
  106. package/src/client/VZCodeContext/useVZCodeState.ts +0 -584
  107. package/src/client/VZKeyboardShortcutsDoc.tsx +0 -148
  108. package/src/client/VZLeft.tsx +0 -28
  109. package/src/client/VZMiddle.tsx +0 -172
  110. package/src/client/VZResizer/index.tsx +0 -128
  111. package/src/client/VZResizer/styles.scss +0 -33
  112. package/src/client/VZRight.tsx +0 -113
  113. package/src/client/VZSettings.tsx +0 -275
  114. package/src/client/VZSidebar/AIChat/ChatInput.tsx +0 -239
  115. package/src/client/VZSidebar/AIChat/DiffView.scss +0 -136
  116. package/src/client/VZSidebar/AIChat/DiffView.tsx +0 -176
  117. package/src/client/VZSidebar/AIChat/Message.tsx +0 -143
  118. package/src/client/VZSidebar/AIChat/MessageList.tsx +0 -205
  119. package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
  120. package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +0 -156
  121. package/src/client/VZSidebar/AIChat/TypingIndicator.tsx +0 -19
  122. package/src/client/VZSidebar/AIChat/index.tsx +0 -273
  123. package/src/client/VZSidebar/AIChat/styles.scss +0 -627
  124. package/src/client/VZSidebar/AIChat/useSpeechRecognition.ts +0 -117
  125. package/src/client/VZSidebar/CreateDirModal.tsx +0 -111
  126. package/src/client/VZSidebar/CreateFileModal.tsx +0 -111
  127. package/src/client/VZSidebar/DeleteConfirmationModal.tsx +0 -76
  128. package/src/client/VZSidebar/DirectoryListing.tsx +0 -89
  129. package/src/client/VZSidebar/EmptyState.tsx +0 -11
  130. package/src/client/VZSidebar/FileListing.tsx +0 -91
  131. package/src/client/VZSidebar/FileTypeIcon.tsx +0 -49
  132. package/src/client/VZSidebar/Item.tsx +0 -237
  133. package/src/client/VZSidebar/Listing.tsx +0 -47
  134. package/src/client/VZSidebar/Search.tsx +0 -527
  135. package/src/client/VZSidebar/VisualEditor.tsx +0 -282
  136. package/src/client/VZSidebar/VoiceChatModal.tsx +0 -121
  137. package/src/client/VZSidebar/aiCopyPaste.ts +0 -199
  138. package/src/client/VZSidebar/index.tsx +0 -728
  139. package/src/client/VZSidebar/styles.scss +0 -612
  140. package/src/client/VZSidebar/useDragAndDrop.tsx +0 -408
  141. package/src/client/bootstrap.ts +0 -26
  142. package/src/client/buildWorker.ts +0 -3
  143. package/src/client/featureFlags.ts +0 -8
  144. package/src/client/generateRequestId.ts +0 -6
  145. package/src/client/getFileTree.ts +0 -53
  146. package/src/client/index.ts +0 -19
  147. package/src/client/main.jsx +0 -10
  148. package/src/client/presenceColor.ts +0 -8
  149. package/src/client/shouldTriggerRun.ts +0 -31
  150. package/src/client/sortFileTree.ts +0 -21
  151. package/src/client/tabsSearchParameters.test.ts +0 -79
  152. package/src/client/tabsSearchParameters.ts +0 -137
  153. package/src/client/themes/index.ts +0 -7
  154. package/src/client/themes/themes.ts +0 -77
  155. package/src/client/themes/uiwImports.ts +0 -32
  156. package/src/client/themes/useDynamicTheme.ts +0 -29
  157. package/src/client/themes/vizhubTheme/colors.ts +0 -80
  158. package/src/client/themes/vizhubTheme/index.ts +0 -193
  159. package/src/client/useActions.ts +0 -288
  160. package/src/client/useESLint/index.ts +0 -72
  161. package/src/client/useESLint/worker.ts +0 -113
  162. package/src/client/useEditorCache.ts +0 -35
  163. package/src/client/useFileCRUD.ts +0 -228
  164. package/src/client/useKeyboardShortcuts.ts +0 -451
  165. package/src/client/useOpenDirectories.ts +0 -99
  166. package/src/client/usePresenceAutoFollow.ts +0 -85
  167. package/src/client/usePrettier/index.ts +0 -178
  168. package/src/client/usePrettier/worker.ts +0 -109
  169. package/src/client/useRunCode.tsx +0 -15
  170. package/src/client/useRuntimeError.ts +0 -32
  171. package/src/client/useSubmitOperation.ts +0 -15
  172. package/src/client/useURLSync.ts +0 -137
  173. package/src/client/usernameLocalStorage.ts +0 -43
  174. package/src/client/utils/fileExtension.ts +0 -10
  175. package/src/client/utils/isImageFile.ts +0 -12
  176. package/src/client/vzReducer/aiChatReducer.ts +0 -44
  177. package/src/client/vzReducer/closeTabReducer.test.ts +0 -205
  178. package/src/client/vzReducer/closeTabsReducer.ts +0 -96
  179. package/src/client/vzReducer/createInitialState.ts +0 -38
  180. package/src/client/vzReducer/editorNoLongerWantsFocusReducer.ts +0 -9
  181. package/src/client/vzReducer/findPane.ts +0 -19
  182. package/src/client/vzReducer/index.ts +0 -250
  183. package/src/client/vzReducer/openTabReducer.test.ts +0 -127
  184. package/src/client/vzReducer/openTabReducer.ts +0 -74
  185. package/src/client/vzReducer/searchReducer.test.ts +0 -292
  186. package/src/client/vzReducer/searchReducer.ts +0 -181
  187. package/src/client/vzReducer/setActiveFileIdReducer.ts +0 -28
  188. package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +0 -76
  189. package/src/client/vzReducer/setIsDocOpenReducer.ts +0 -9
  190. package/src/client/vzReducer/setIsSettingsOpenReducer.ts +0 -9
  191. package/src/client/vzReducer/setThemeReducer.ts +0 -9
  192. package/src/client/vzReducer/setUsernameReducer.ts +0 -9
  193. package/src/client/vzReducer/splitCurrentPaneReducer.ts +0 -66
  194. package/src/client/vzReducer/toggleAutoFollowReducer.ts +0 -12
  195. package/src/client/vzReducer/updatePane.ts +0 -40
  196. package/src/client/vzReducer/updatePresenceIndicatorReducer.ts +0 -30
  197. package/src/client/vzReducer/visualEditorReducer.ts +0 -9
  198. package/src/reactRouterExports.ts +0 -15
  199. package/src/runCode.ts +0 -27
  200. package/src/server/aiChatHandler/aiEditing.ts +0 -152
  201. package/src/server/aiChatHandler/chatOperations.ts +0 -510
  202. package/src/server/aiChatHandler/errorHandling.ts +0 -66
  203. package/src/server/aiChatHandler/index.ts +0 -200
  204. package/src/server/aiChatHandler/llmStreaming.ts +0 -419
  205. package/src/server/aiChatHandler/undoHandler.ts +0 -97
  206. package/src/server/aiChatHandler/validation.ts +0 -24
  207. package/src/server/computeInitialDocument.ts +0 -220
  208. package/src/server/generateAIResponse.ts +0 -188
  209. package/src/server/handleAIAssist.ts +0 -53
  210. package/src/server/handleAIChatUndo.ts +0 -2
  211. package/src/server/handleAICopilot.ts +0 -97
  212. package/src/server/index.ts +0 -388
  213. package/src/server/livekit.ts +0 -24
  214. package/src/server/prettier.ts +0 -115
  215. package/src/submitOperation.ts +0 -25
  216. package/src/types.ts +0 -205
  217. package/src/utils/fileDiff.ts +0 -117
  218. package/src/vite-env.d.ts +0 -10
  219. /package/{src/server/handleAIChatMessage.ts → dist/server/handleAIChatMessage.js} +0 -0
  220. /package/{src/server/isDirectory.ts → dist/server/isDirectory.js} +0 -0
@@ -1,43 +0,0 @@
1
- // This module deals with storing and accessing the
2
- // username in local storage.
3
- import { useEffect, useRef } from 'react';
4
- import { Username } from '../types';
5
-
6
- const localStoragePropertyName = 'vzCodeUsername';
7
-
8
- const initialUsernameDefault = 'Anonymous';
9
-
10
- // Gets the username from local storage.
11
- export const useInitialUsername = (): Username => {
12
- let initialUsername: Username = initialUsernameDefault;
13
-
14
- // If we're in the browser,
15
- if (typeof window !== 'undefined') {
16
- //check localStorage for a previously stored width.
17
- const initialUsernameFromLocalStorage: string | null =
18
- window.localStorage.getItem(localStoragePropertyName);
19
-
20
- // If there is a previously stored width,
21
- if (initialUsernameFromLocalStorage !== null) {
22
- // use it as the initial width.
23
- initialUsername = initialUsernameFromLocalStorage;
24
- }
25
- } else {
26
- // If we're not in the browser, use the default initial width.
27
- }
28
- return initialUsername;
29
- };
30
-
31
- // Stores the username to local storage.
32
- export const usePersistUsername = (username: Username) => {
33
- const previousUsername = useRef<Username>(username);
34
- useEffect(() => {
35
- if (previousUsername.current !== username) {
36
- previousUsername.current = username;
37
- window.localStorage.setItem(
38
- 'vzCodeUsername',
39
- username,
40
- );
41
- }
42
- }, [username]);
43
- };
@@ -1,10 +0,0 @@
1
- /**
2
- * Utility function to extract file extension from a file name.
3
- * @param fileName - The name of the file (e.g., "index.html", "script.js")
4
- * @returns The file extension without the dot (e.g., "html", "js") or undefined if no extension
5
- */
6
- export const getFileExtension = (
7
- fileName: string,
8
- ): string | undefined => {
9
- return fileName.split('.').pop();
10
- };
@@ -1,12 +0,0 @@
1
- /**
2
- * Utility function to check if a file is an image based on its name.
3
- * @param fileName - The name of the file (e.g., "image.png", "photo.jpg")
4
- * @returns true if the file is an image, false otherwise
5
- */
6
- export const isImageFile = (fileName: string): boolean => {
7
- return (
8
- fileName.match(
9
- /\.(png|jpg|jpeg|gif|bmp|svg|webp)$/i,
10
- ) !== null
11
- );
12
- };
@@ -1,44 +0,0 @@
1
- import { VZState, VZAction } from '.';
2
-
3
- export const setIsAIChatOpenReducer = (
4
- state: VZState,
5
- action: VZAction,
6
- ): VZState => {
7
- if (action.type === 'set_is_ai_chat_open') {
8
- return {
9
- ...state,
10
- isAIChatOpen: action.value,
11
- // When opening AI chat, close search
12
- isSearchOpen: action.value
13
- ? false
14
- : state.isSearchOpen,
15
- };
16
- }
17
- return state;
18
- };
19
-
20
- export const toggleAIChatFocusedReducer = (
21
- state: VZState,
22
- action: VZAction,
23
- ): VZState => {
24
- if (action.type === 'toggle_ai_chat_focused') {
25
- return {
26
- ...state,
27
- aiChatFocused: !state.aiChatFocused,
28
- };
29
- }
30
- return state;
31
- };
32
-
33
- export const setAIChatModeReducer = (
34
- state: VZState,
35
- action: VZAction,
36
- ): VZState => {
37
- if (action.type === 'set_ai_chat_mode') {
38
- return {
39
- ...state,
40
- aiChatMode: action.mode,
41
- };
42
- }
43
- return state;
44
- };
@@ -1,205 +0,0 @@
1
- import { assert, describe, expect, it } from 'vitest';
2
- import { closeTabsReducer } from './closeTabsReducer';
3
- import { VZAction, VZState, createInitialState } from '.';
4
- import { defaultTheme } from '../themes';
5
-
6
- const initialState: VZState = createInitialState({
7
- defaultTheme,
8
- });
9
-
10
- describe('closeTabsReducer', () => {
11
- it('Closes an existing tab', () => {
12
- const action: VZAction = {
13
- type: 'close_tabs',
14
- fileIdsToClose: ['file1'],
15
- };
16
-
17
- const stateWithTabs = {
18
- ...initialState,
19
- pane: {
20
- ...initialState.pane,
21
- tabList: [{ fileId: 'file1', isTransient: false }],
22
- activeFileId: 'file1',
23
- },
24
- };
25
-
26
- const newState = closeTabsReducer(
27
- stateWithTabs,
28
- action,
29
- );
30
-
31
- assert(newState.pane.type === 'leafPane');
32
- expect(newState.pane.tabList.length).toBe(0);
33
- expect(newState.pane.activeFileId).toBeNull();
34
- });
35
-
36
- it('Keeps other tabs open', () => {
37
- const action: VZAction = {
38
- type: 'close_tabs',
39
- fileIdsToClose: ['file2'],
40
- };
41
- const stateWithTabs = {
42
- ...initialState,
43
- pane: {
44
- ...initialState.pane,
45
- tabList: [
46
- { fileId: 'file1', isTransient: false },
47
- { fileId: 'file2', isTransient: false },
48
- ],
49
- activeFileId: 'file1',
50
- },
51
- };
52
-
53
- const newState = closeTabsReducer(
54
- stateWithTabs,
55
- action,
56
- );
57
-
58
- assert(newState.pane.type === 'leafPane');
59
- expect(newState.pane.tabList.length).toBe(1);
60
- expect(newState.pane.tabList[0].fileId).toBe('file1');
61
- expect(newState.pane.activeFileId).toBe('file1');
62
- });
63
-
64
- it('Activates previous tab after closing an active tab', () => {
65
- const action: VZAction = {
66
- type: 'close_tabs',
67
- fileIdsToClose: ['file2'],
68
- };
69
- const stateWithTabs: VZState = {
70
- ...initialState,
71
- pane: {
72
- ...initialState.pane,
73
- type: 'leafPane',
74
- tabList: [
75
- { fileId: 'file1', isTransient: false },
76
- { fileId: 'file2', isTransient: false },
77
- { fileId: 'file3', isTransient: false },
78
- ],
79
- activeFileId: 'file2',
80
- },
81
- };
82
-
83
- const newState = closeTabsReducer(
84
- stateWithTabs,
85
- action,
86
- );
87
-
88
- assert(newState.pane.type === 'leafPane');
89
- expect(newState.pane.tabList.length).toBe(2);
90
- expect(newState.pane.activeFileId).toBe('file1'); // should switch to the previous tab
91
- });
92
-
93
- it('Does not modify the state if closing non-existing tabs', () => {
94
- const action: VZAction = {
95
- type: 'close_tabs',
96
- fileIdsToClose: ['file4'],
97
- };
98
- const stateWithTabs = {
99
- ...initialState,
100
- pane: {
101
- ...initialState.pane,
102
- tabList: [
103
- { fileId: 'file1', isTransient: false },
104
- { fileId: 'file2', isTransient: false },
105
- { fileId: 'file3', isTransient: false },
106
- ],
107
- activeFileId: 'file2',
108
- },
109
- };
110
-
111
- const newState = closeTabsReducer(
112
- stateWithTabs,
113
- action,
114
- );
115
-
116
- expect(newState).toEqual(stateWithTabs);
117
- });
118
-
119
- it('Closes a tab that is not currently active', () => {
120
- const stateWithMultipleTabs = {
121
- ...initialState,
122
- pane: {
123
- ...initialState.pane,
124
- tabList: [
125
- { fileId: 'file1', isTransient: false },
126
- { fileId: 'file2', isTransient: false },
127
- { fileId: 'file3', isTransient: false },
128
- ],
129
- activeFileId: 'file3',
130
- },
131
- };
132
-
133
- const action: VZAction = {
134
- type: 'close_tabs',
135
- fileIdsToClose: ['file2'],
136
- };
137
-
138
- const newState = closeTabsReducer(
139
- stateWithMultipleTabs,
140
- action,
141
- );
142
-
143
- assert(newState.pane.type === 'leafPane');
144
- expect(newState.pane.tabList.length).toBe(2);
145
- expect(newState.pane.activeFileId).toBe('file3'); // remains unchanged
146
- });
147
-
148
- it('Closes the first tab out of many, when it is active', () => {
149
- const stateWithMultipleTabs = {
150
- ...initialState,
151
- pane: {
152
- ...initialState.pane,
153
- tabList: [
154
- { fileId: 'file1', isTransient: false },
155
- { fileId: 'file2', isTransient: false },
156
- { fileId: 'file3', isTransient: false },
157
- ],
158
- activeFileId: 'file1',
159
- },
160
- };
161
-
162
- const action: VZAction = {
163
- type: 'close_tabs',
164
- fileIdsToClose: ['file1'],
165
- };
166
-
167
- const newState = closeTabsReducer(
168
- stateWithMultipleTabs,
169
- action,
170
- );
171
-
172
- assert(newState.pane.type === 'leafPane');
173
- expect(newState.pane.tabList.length).toBe(2);
174
- expect(newState.pane.activeFileId).toBe('file2'); // switches to the next available tab
175
- });
176
-
177
- it('Closes multiple tabs at once', () => {
178
- const stateWithMultipleTabs = {
179
- ...initialState,
180
- pane: {
181
- ...initialState.pane,
182
- tabList: [
183
- { fileId: 'file1', isTransient: false },
184
- { fileId: 'file2', isTransient: false },
185
- { fileId: 'file3', isTransient: false },
186
- ],
187
- activeFileId: 'file2',
188
- },
189
- };
190
-
191
- const action: VZAction = {
192
- type: 'close_tabs',
193
- fileIdsToClose: ['file1', 'file2'],
194
- };
195
-
196
- const newState = closeTabsReducer(
197
- stateWithMultipleTabs,
198
- action,
199
- );
200
-
201
- assert(newState.pane.type === 'leafPane');
202
- expect(newState.pane.tabList.length).toBe(1);
203
- expect(newState.pane.activeFileId).toBe('file3'); // switches to the next available tab
204
- });
205
- });
@@ -1,96 +0,0 @@
1
- import { VZAction, VZState } from '.';
2
- import { Pane, PaneId, TabState } from '../../types';
3
- import { VizFileId } from '@vizhub/viz-types';
4
- import { findPane } from './findPane';
5
- import { updatePane } from './updatePane';
6
-
7
- export const closeTabsReducer = (
8
- state: VZState,
9
- action: VZAction,
10
- ): VZState => {
11
- if (action.type !== 'close_tabs') {
12
- return state;
13
- }
14
-
15
- const { pane, activePaneId } = state;
16
- const activePane: Pane = findPane(pane, activePaneId);
17
-
18
- if (activePane.type !== 'leafPane') {
19
- throw new Error(
20
- 'closeTabsReducer: activePane is not a leafPane',
21
- );
22
- }
23
-
24
- // Derive the new tab list by filtering out the tabs to close.
25
- const newTabList: Array<TabState> =
26
- activePane.tabList.filter(
27
- (tabState) =>
28
- !action.fileIdsToClose.includes(tabState.fileId),
29
- );
30
-
31
- // If the active tab wasn't closed, keep it active.
32
- if (
33
- !action.fileIdsToClose.includes(
34
- activePane.activeFileId!,
35
- )
36
- ) {
37
- return {
38
- ...state,
39
- pane: updatePane({
40
- pane,
41
- activePaneId,
42
- newTabList,
43
- }),
44
- };
45
- }
46
-
47
- // Otherwise, we'll need to also find a new active tab.
48
- let newActiveFileId: VizFileId | null = null;
49
-
50
- // The question becomes: which tab should be active now?
51
- // - Either the tab to the left or right of the closed tab.
52
-
53
- // Try getting the previous available tab first.
54
- const originalIndex = activePane.tabList.findIndex(
55
- (tabState) =>
56
- tabState.fileId === activePane.activeFileId,
57
- );
58
- for (let i = originalIndex - 1; i >= 0; i--) {
59
- if (
60
- !action.fileIdsToClose.includes(
61
- activePane.tabList[i].fileId,
62
- )
63
- ) {
64
- newActiveFileId = activePane.tabList[i].fileId;
65
- break;
66
- }
67
- }
68
-
69
- // If no previous tab available, get the next available one.
70
- if (!newActiveFileId) {
71
- for (
72
- let i = originalIndex + 1;
73
- i < activePane.tabList.length;
74
- i++
75
- ) {
76
- if (
77
- !action.fileIdsToClose.includes(
78
- activePane.tabList[i].fileId,
79
- )
80
- ) {
81
- newActiveFileId = activePane.tabList[i].fileId;
82
- break;
83
- }
84
- }
85
- }
86
-
87
- return {
88
- ...state,
89
- pane: updatePane({
90
- pane,
91
- activePaneId,
92
- newTabList,
93
- newActiveFileId,
94
- }),
95
- };
96
- };
@@ -1,38 +0,0 @@
1
- import { VZState } from '.';
2
- import { Username } from '../../types';
3
- import { ThemeLabel } from '../themes';
4
-
5
- export const createInitialState = ({
6
- defaultTheme,
7
- initialUsername = 'Anonymous',
8
- }: {
9
- defaultTheme: ThemeLabel;
10
- initialUsername?: Username;
11
- }): VZState => ({
12
- pane: {
13
- id: 'root',
14
- type: 'leafPane',
15
- tabList: [],
16
- activeFileId: null,
17
- },
18
- activePaneId: 'root',
19
- theme: defaultTheme,
20
- search: {
21
- pattern: '',
22
- results: {},
23
- focused: false,
24
- focusedIndex: null,
25
- focusedChildIndex: null,
26
- },
27
- isVisualEditorOpen: false,
28
- isSearchOpen: false,
29
- isAIChatOpen: true,
30
- aiChatFocused: false,
31
- aiChatMode: 'edit',
32
- isSettingsOpen: false,
33
- isDocOpen: false,
34
- editorWantsFocus: false,
35
- username: initialUsername,
36
- enableAutoFollow: true,
37
- sidebarPresenceIndicators: [],
38
- });
@@ -1,9 +0,0 @@
1
- import { VZAction, VZState } from '.';
2
-
3
- export const editorNoLongerWantsFocusReducer = (
4
- state: VZState,
5
- action: VZAction,
6
- ): VZState =>
7
- action.type === 'editor_no_longer_wants_focus'
8
- ? { ...state, editorWantsFocus: false }
9
- : state;
@@ -1,19 +0,0 @@
1
- import { Pane, PaneId } from '../../types';
2
-
3
- // Recursively finds a pane by id, given a root pane node.
4
- export const findPane = (
5
- pane: Pane,
6
- paneId: PaneId,
7
- ): Pane => {
8
- if (pane.id === paneId) {
9
- return pane;
10
- }
11
- if (pane.type === 'splitPane') {
12
- for (const child of pane.children) {
13
- const foundPane = findPane(child, paneId);
14
- if (foundPane) {
15
- return foundPane;
16
- }
17
- }
18
- }
19
- };