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,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
- };