@@ -15,11 +15,11 @@ import { FileIcon } from './FileIcon';
1515import { getFileName } from '../lib/utils' ;
1616
1717export function ArtifactsDrawer ( ) {
18- const {
18+ const {
1919 fs,
20- openFiles,
21- activeFile,
22- openFile,
20+ openFiles,
21+ activeFile,
22+ openFile,
2323 closeFile,
2424 } = useArtifacts ( ) ;
2525
@@ -31,21 +31,14 @@ export function ArtifactsDrawer() {
3131 useEffect ( ( ) => {
3232 if ( ! fs ) return ;
3333
34- const unsubscribeUpdated = fs . subscribe ( 'fileUpdated' , ( updatedPath : string ) => {
35- // If the updated file is currently open, close and reopen it to refresh content
36- if ( activeFile === updatedPath ) {
37- closeFile ( updatedPath ) ;
38- // Reopen after a brief delay to ensure clean state
39- setTimeout ( ( ) => {
40- openFile ( updatedPath ) ;
41- } , 10 ) ;
42- }
34+ const unsubscribeUpdated = fs . subscribe ( 'fileUpdated' , ( _updatedPath : string ) => {
35+ // No-op: components consume updated content from filesystem state without forcing tab re-mount.
4336 } ) ;
4437
4538 return ( ) => {
4639 unsubscribeUpdated ( ) ;
4740 } ;
48- } , [ fs , activeFile , closeFile , openFile ] ) ;
41+ } , [ fs ] ) ;
4942
5043 // Get all files sorted by path
5144 const files = fs ? fs . listFiles ( ) . sort ( ( a , b ) => a . path . localeCompare ( b . path ) ) : [ ] ;
@@ -72,26 +65,26 @@ export function ArtifactsDrawer() {
7265 const handleDrop = async ( e : React . DragEvent ) => {
7366 e . preventDefault ( ) ;
7467 setIsDragOver ( false ) ;
75-
68+
7669 // Clear any pending timeout
7770 if ( dragTimeoutRef . current ) {
7871 clearTimeout ( dragTimeoutRef . current ) ;
7972 dragTimeoutRef . current = null ;
8073 }
8174
8275 const files = Array . from ( e . dataTransfer . files ) ;
83-
76+
8477 for ( const file of files ) {
8578 try {
8679 const path = `/${ file . name } ` ;
87-
80+
8881 // Read the file content as text
8982 const content = await file . text ( ) ;
90-
83+
9184 // Create the file with string content
9285 if ( fs ) {
9386 fs . createFile ( path , content , file . type ) ;
94-
87+
9588 // Open the file in a tab
9689 openFile ( path ) ;
9790 }
@@ -103,16 +96,16 @@ export function ArtifactsDrawer() {
10396
10497 const handleDragOver = ( e : React . DragEvent ) => {
10598 e . preventDefault ( ) ;
106-
99+
107100 if ( ! isDragOver ) {
108101 setIsDragOver ( true ) ;
109102 }
110-
103+
111104 // Clear any existing timeout and set a new one
112105 if ( dragTimeoutRef . current ) {
113106 clearTimeout ( dragTimeoutRef . current ) ;
114107 }
115-
108+
116109 // Reset drag state after a short delay if no more drag events
117110 dragTimeoutRef . current = setTimeout ( ( ) => {
118111 setIsDragOver ( false ) ;
@@ -139,8 +132,8 @@ export function ArtifactsDrawer() {
139132 No File Selected
140133 </ h3 >
141134 < p className = "text-sm text-neutral-600 dark:text-neutral-400 mb-4" >
142- { files . length === 0
143- ? "Files created by the AI will appear here"
135+ { files . length === 0
136+ ? "Files created by the AI will appear here"
144137 : "Select a file from the tabs above or use the file browser" }
145138 </ p >
146139 { files . length > 0 && (
@@ -168,14 +161,14 @@ export function ArtifactsDrawer() {
168161 case 'csv' :
169162 return < CsvEditor content = { file . content } /> ;
170163 case 'mermaid' :
171- return < MermaidEditor content = { file . content } /> ;
164+ return < MermaidEditor path = { file . path } content = { file . content } /> ;
172165 case 'markdown' :
173166 return < MarkdownEditor content = { file . content } /> ;
174167 case 'code' :
175168 return (
176- < CodeEditor
177- content = { file . content }
178- language = { artifactLanguage ( file . path ) }
169+ < CodeEditor
170+ content = { file . content }
171+ language = { artifactLanguage ( file . path ) }
179172 />
180173 ) ;
181174 case 'text' :
@@ -185,7 +178,7 @@ export function ArtifactsDrawer() {
185178 } ;
186179
187180 return (
188- < div
181+ < div
189182 className = "h-full flex flex-col rounded-xl overflow-hidden animate-in fade-in duration-200 relative bg-white dark:bg-neutral-900"
190183 onDragOver = { handleDragOver }
191184 onDrop = { handleDrop }
@@ -204,17 +197,16 @@ export function ArtifactsDrawer() {
204197 </ div >
205198 </ div >
206199 ) }
207-
200+
208201 { /* Tab Bar with File Browser Button - Fixed at top */ }
209202 < div className = "flex-shrink-0 border-b border-neutral-200 dark:border-neutral-600 relative h-9 flex" >
210203 { /* File Browser Button - Expands to match browser width */ }
211204 < Button
212205 onClick = { ( ) => setShowFileBrowser ( ! showFileBrowser ) }
213- className = { `flex items-center px-2.5 h-full text-xs flex-shrink-0 border-r border-neutral-200 dark:border-neutral-600 transition-all duration-300 ease-out text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-100/50 dark:hover:bg-neutral-700/30 ${
214- showFileBrowser
206+ className = { `flex items-center px-2.5 h-full text-xs flex-shrink-0 border-r border-neutral-200 dark:border-neutral-600 transition-all duration-300 ease-out text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-100/50 dark:hover:bg-neutral-700/30 ${ showFileBrowser
215207 ? 'w-64 justify-start gap-1.5'
216208 : 'w-auto justify-center'
217- } `}
209+ } `}
218210 title = "Browse files"
219211 >
220212 < FolderTree size = { 14 } className = "flex-shrink-0" />
@@ -232,19 +224,18 @@ export function ArtifactsDrawer() {
232224 { openFiles . map ( ( path ) => {
233225 const file = fs ?. getFile ( path ) ;
234226 if ( ! file ) return null ;
235-
227+
236228 const filename = getFileName ( path ) ;
237229 const isActive = activeFile === path ;
238230
239231 return (
240232 < Button
241233 key = { path }
242234 onClick = { ( ) => selectFile ( path ) }
243- className = { `flex items-center gap-1.5 px-3 h-full text-xs border-r border-neutral-200 dark:border-neutral-600 min-w-0 flex-shrink-0 whitespace-nowrap ${
244- isActive
235+ className = { `flex items-center gap-1.5 px-3 h-full text-xs border-r border-neutral-200 dark:border-neutral-600 min-w-0 flex-shrink-0 whitespace-nowrap ${ isActive
245236 ? 'text-neutral-900 dark:text-neutral-100 border-t-2 border-t-blue-500'
246237 : 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-100/50 dark:hover:bg-neutral-700/30'
247- } transition-colors`}
238+ } transition-colors`}
248239 style = { { minWidth : 'max-content' } }
249240 >
250241 < FileIcon name = { path } />
@@ -270,9 +261,8 @@ export function ArtifactsDrawer() {
270261 { /* Content Area with Sidebar */ }
271262 < div className = "flex-1 flex overflow-hidden" >
272263 { /* Left Side Panel - File Browser */ }
273- < div className = { `transition-all duration-300 ease-out ${
274- showFileBrowser ? 'w-64' : 'w-0'
275- } flex-shrink-0 overflow-hidden ${ showFileBrowser ? 'border-r border-neutral-200 dark:border-neutral-600' : '' } `} >
264+ < div className = { `transition-all duration-300 ease-out ${ showFileBrowser ? 'w-64' : 'w-0'
265+ } flex-shrink-0 overflow-hidden ${ showFileBrowser ? 'border-r border-neutral-200 dark:border-neutral-600' : '' } `} >
276266 { showFileBrowser && fs && (
277267 < ArtifactsBrowser
278268 fs = { fs }
@@ -281,7 +271,7 @@ export function ArtifactsDrawer() {
281271 />
282272 ) }
283273 </ div >
284-
274+
285275 { /* Main Content Area */ }
286276 < div className = "flex-1 flex flex-col overflow-hidden" >
287277 { renderEditor ( ) }
0 commit comments