1*c7504584SBartosz Kaszubowskiimport { FileCode01Icon, FolderIcon } from '@expo/styleguide-icons'; 2*c7504584SBartosz Kaszubowskiimport { HTMLAttributes, ReactNode } from 'react'; 3*c7504584SBartosz Kaszubowski 4*c7504584SBartosz Kaszubowskitype FileTreeProps = HTMLAttributes<HTMLDivElement> & { 5*c7504584SBartosz Kaszubowski files?: string[]; 6*c7504584SBartosz Kaszubowski}; 7*c7504584SBartosz Kaszubowski 8*c7504584SBartosz Kaszubowskitype FileObject = { 9*c7504584SBartosz Kaszubowski [key: string]: FileObject; 10*c7504584SBartosz Kaszubowski}; 11*c7504584SBartosz Kaszubowski 12*c7504584SBartosz Kaszubowskiexport function FileTree({ files = [], ...rest }: FileTreeProps) { 13*c7504584SBartosz Kaszubowski return ( 14*c7504584SBartosz Kaszubowski <div className="text-xs border border-default rounded-md bg-default mb-4 p-2 pb-4" {...rest}> 15*c7504584SBartosz Kaszubowski {renderStructure(generateStructure(files))} 16*c7504584SBartosz Kaszubowski </div> 17*c7504584SBartosz Kaszubowski ); 18*c7504584SBartosz Kaszubowski} 19*c7504584SBartosz Kaszubowski 20*c7504584SBartosz Kaszubowskifunction generateStructure(files: string[]): FileObject { 21*c7504584SBartosz Kaszubowski const structure = {}; 22*c7504584SBartosz Kaszubowski files.forEach(path => 23*c7504584SBartosz Kaszubowski path.split('/').reduce((acc: FileObject, key) => acc[key] ?? (acc[key] = {}), structure) 24*c7504584SBartosz Kaszubowski ); 25*c7504584SBartosz Kaszubowski return structure; 26*c7504584SBartosz Kaszubowski} 27*c7504584SBartosz Kaszubowski 28*c7504584SBartosz Kaszubowskifunction renderStructure(structure: FileObject, level = 0): ReactNode { 29*c7504584SBartosz Kaszubowski return Object.entries(structure).map(([key, value]) => { 30*c7504584SBartosz Kaszubowski return Object.keys(value).length ? ( 31*c7504584SBartosz Kaszubowski <div className="mt-1 pt-1 px-2 rounded-sm flex flex-col"> 32*c7504584SBartosz Kaszubowski <div className="flex items-center"> 33*c7504584SBartosz Kaszubowski {' '.repeat(level)} 34*c7504584SBartosz Kaszubowski <FolderIcon className="text-icon-tertiary mr-2 opacity-60" /> 35*c7504584SBartosz Kaszubowski <code className="text-secondary">{key}</code> 36*c7504584SBartosz Kaszubowski </div> 37*c7504584SBartosz Kaszubowski {renderStructure(value, level + 1)} 38*c7504584SBartosz Kaszubowski </div> 39*c7504584SBartosz Kaszubowski ) : ( 40*c7504584SBartosz Kaszubowski <div className="mt-1 pl-3 pt-1 px-2 rounded-sm flex items-center"> 41*c7504584SBartosz Kaszubowski {' '.repeat(level - 1)} 42*c7504584SBartosz Kaszubowski <FileCode01Icon className="text-icon-tertiary mr-2" /> 43*c7504584SBartosz Kaszubowski <code className="text-default">{key}</code> 44*c7504584SBartosz Kaszubowski </div> 45*c7504584SBartosz Kaszubowski ); 46*c7504584SBartosz Kaszubowski }); 47*c7504584SBartosz Kaszubowski} 48