1- import { useState , type MouseEvent } from 'react'
1+ import { useState , type MouseEvent , useEffect } from 'react'
22import {
33 DocumentIcon ,
44 XCircleIcon ,
@@ -19,8 +19,6 @@ interface PropsFile extends WithConfirmation {
1919 file : ModelFile
2020}
2121
22- const CSS_ICON_SIZE = 'w-4 h-4'
23-
2422export default function File ( {
2523 file,
2624 setConfirmation,
@@ -29,12 +27,17 @@ export default function File({
2927 const tabs = useStoreEditor ( s => s . tabs )
3028 const closeTab = useStoreEditor ( s => s . closeTab )
3129
30+ const selectedFile = useStoreFileTree ( s => s . selectedFile )
3231 const selectFile = useStoreFileTree ( s => s . selectFile )
3332 const refreshProject = useStoreFileTree ( s => s . refreshProject )
3433
3534 const [ isLoading , setIsLoading ] = useState ( false )
3635 const [ newName , setNewName ] = useState < string > ( )
3736
37+ useEffect ( ( ) => {
38+ selectFile ( tab . file )
39+ } , [ tab ] )
40+
3841 function remove ( ) : void {
3942 if ( isLoading ) return
4043
@@ -43,7 +46,7 @@ export default function File({
4346 deleteFileApiFilesPathDelete ( file . path )
4447 . then ( response => {
4548 if ( ( response as unknown as { ok : boolean } ) . ok ) {
46- closeTab ( file . id )
49+ closeTab ( file )
4750
4851 file . parent ?. removeFile ( file )
4952
@@ -107,14 +110,14 @@ export default function File({
107110 < span
108111 className = { clsx (
109112 'whitespace-nowrap group/file pl-3 pr-2 py-[0.125rem] flex rounded-md' ,
110- 'hover:bg-neutral-100 dark:hover:bg-dark-lighter ' ,
113+ 'hover:bg-neutral-100 dark:hover:bg-dark-lighter' ,
111114 file . is_supported &&
112115 'group hover:bg-neutral-100 dark:hover:bg-dark-lighter' ,
113116 isFalse ( isStringEmptyOrNil ( newName ) ) && 'bg-primary-800' ,
114- tabs . has ( file . id )
117+ tabs . has ( file )
115118 ? 'text-brand-500'
116119 : 'text-neutral-500 dark:text-neutral-100' ,
117- file === tab . file && 'bg-neutral-100 dark:bg-dark-lighter' ,
120+ file === selectedFile && 'bg-neutral-100 dark:bg-dark-lighter' ,
118121 ) }
119122 >
120123 < span
@@ -125,71 +128,120 @@ export default function File({
125128 < div className = "flex items-center" >
126129 < DocumentIcon
127130 className = { clsx (
128- `inline-block ${ CSS_ICON_SIZE } mr-2` ,
129- file === tab . file
131+ `inline-block w-4 h-4 mr-2` ,
132+ file === selectedFile
130133 ? 'text-brand-500'
131134 : 'text-neutral-500 dark:text-neutral-100' ,
132135 ) }
133136 />
134137 </ div >
135138 { isStringEmptyOrNil ( newName ) ? (
136139 < >
137- < span
138- onClick = { ( e : MouseEvent ) => {
139- e . stopPropagation ( )
140-
141- file . is_supported && file !== tab . file && selectFile ( file )
142- } }
143- onDoubleClick = { ( e : MouseEvent ) => {
144- e . stopPropagation ( )
145-
146- setNewName ( file . name )
147- } }
148- className = { clsx (
149- 'w-full overflow-hidden overflow-ellipsis cursor-default' ,
150- ! file . is_supported && 'opacity-50 cursor-not-allowed' ,
151- ) }
152- >
153- { file . name }
154- </ span >
155- < span
156- className = "flex items-center invisible group-hover/file:visible min-w-8"
157- onClick = { ( e : MouseEvent ) => {
158- e . stopPropagation ( )
159-
160- removeWithConfirmation ( )
161- } }
162- >
163- < XCircleIcon
164- className = { `inline-block ${ CSS_ICON_SIZE } ml-2 text-danger-500 cursor-pointer` }
165- />
166- </ span >
140+ < FileName
141+ file = { file }
142+ setNewName = { setNewName }
143+ />
144+ < FileActions removeWithConfirmation = { removeWithConfirmation } />
167145 </ >
168146 ) : (
169- < div className = "w-full flex items-center" >
170- < input
171- type = "text"
172- className = "w-full overflow-hidden overflow-ellipsis bg-primary-900 text-primary-100"
173- value = { newName === '' ? file . name : newName }
174- onInput = { ( e : any ) => {
175- e . stopPropagation ( )
176-
177- setNewName ( e . target . value )
178- } }
179- />
180- < div className = "flex" >
181- < CheckCircleIcon
182- className = { `inline-block ${ CSS_ICON_SIZE } ml-2 text-success-500 cursor-pointer` }
183- onClick = { ( e : MouseEvent ) => {
184- e . stopPropagation ( )
185-
186- rename ( )
187- } }
188- />
189- </ div >
190- </ div >
147+ < FileRename
148+ file = { file }
149+ newName = { newName }
150+ setNewName = { setNewName }
151+ rename = { rename }
152+ />
191153 ) }
192154 </ span >
193155 </ span >
194156 )
195157}
158+
159+ function FileName ( {
160+ file,
161+ setNewName,
162+ } : {
163+ file : ModelFile
164+ setNewName : ( name : string ) => void
165+ } ) : JSX . Element {
166+ const selectedFile = useStoreFileTree ( s => s . selectedFile )
167+ const selectFile = useStoreFileTree ( s => s . selectFile )
168+
169+ return (
170+ < span
171+ onClick = { ( e : MouseEvent ) => {
172+ e . stopPropagation ( )
173+
174+ file . is_supported && file !== selectedFile && selectFile ( file )
175+ } }
176+ onDoubleClick = { ( e : MouseEvent ) => {
177+ e . stopPropagation ( )
178+
179+ setNewName ( file . name )
180+ } }
181+ className = { clsx (
182+ 'w-full overflow-hidden overflow-ellipsis cursor-default' ,
183+ ! file . is_supported && 'opacity-50 cursor-not-allowed' ,
184+ ) }
185+ >
186+ { file . name }
187+ </ span >
188+ )
189+ }
190+
191+ function FileRename ( {
192+ file,
193+ newName,
194+ setNewName,
195+ rename,
196+ } : {
197+ file : ModelFile
198+ newName ?: string
199+ setNewName : ( name : string ) => void
200+ rename : ( ) => void
201+ } ) : JSX . Element {
202+ return (
203+ < div className = "w-full flex items-center" >
204+ < input
205+ type = "text"
206+ className = "w-full overflow-hidden overflow-ellipsis bg-primary-900 text-primary-100"
207+ value = { newName === '' ? file . name : newName }
208+ onInput = { ( e : any ) => {
209+ e . stopPropagation ( )
210+
211+ setNewName ( e . target . value )
212+ } }
213+ />
214+ < div className = "flex" >
215+ < CheckCircleIcon
216+ className = { `inline-block w-4 h-4 ml-2 text-success-500 cursor-pointer` }
217+ onClick = { ( e : MouseEvent ) => {
218+ e . stopPropagation ( )
219+
220+ rename ( )
221+ } }
222+ />
223+ </ div >
224+ </ div >
225+ )
226+ }
227+
228+ function FileActions ( {
229+ removeWithConfirmation,
230+ } : {
231+ removeWithConfirmation : ( ) => void
232+ } ) : JSX . Element {
233+ return (
234+ < span
235+ className = "flex items-center invisible group-hover/file:visible min-w-8"
236+ onClick = { ( e : MouseEvent ) => {
237+ e . stopPropagation ( )
238+
239+ removeWithConfirmation ( )
240+ } }
241+ >
242+ < XCircleIcon
243+ className = { `inline-block w-4 h-4 ml-2 text-danger-500 cursor-pointer` }
244+ />
245+ </ span >
246+ )
247+ }
0 commit comments