1+ import { useState } from 'react' ;
2+ import { notify } from 'stackpress/view/client' ;
3+ import Code from './Code.js' ;
4+
5+ export type File = {
6+ type : 'file' ,
7+ id : string ,
8+ name : string ,
9+ level : number ,
10+ content : string
11+ } ;
12+ export type Folder = {
13+ type : 'folder' ,
14+ name : string ,
15+ level : number
16+ } ;
17+ export type EditorTabsProps = {
18+ active : string ,
19+ files : ( File | Folder ) [ ] ,
20+ open : ( file : string ) => void
21+ } ;
22+ export type EditorFilesProps = {
23+ active : string ,
24+ files : ( File | Folder ) [ ] ,
25+ className ?: string
26+ } ;
27+ export type EditorExplorerProps = {
28+ active : string ,
29+ files : ( File | Folder ) [ ] ,
30+ open : ( file : string ) => void
31+ } ;
32+ export type EditorProps = {
33+ files : ( File | Folder ) [ ] ,
34+ value : string ,
35+ className ?: string ,
36+ leftClassName ?: string ,
37+ topClassName ?: string ,
38+ mainClassName ?: string ,
39+ title ?: string
40+ } ;
41+
42+ export function EditorExplorer ( props : EditorExplorerProps ) {
43+ const { active, files, open } = props ;
44+ return (
45+ < div className = "flex-grow overflow-auto px-pb-20" >
46+ { files . map ( ( item , index ) => {
47+ const left = 5 + ( item . level * 15 ) ;
48+ if ( item . type === 'folder' ) {
49+ return (
50+ < div
51+ key = { `explorer-${ index } ` }
52+ className = "flex items-center"
53+ style = { { paddingLeft : `${ left } px` } }
54+ >
55+ < i className = "inline-block px-fs-10 px-mr-5 fas fa-chevron-down" > </ i >
56+ { item . name }
57+ </ div >
58+ ) ;
59+ }
60+ const icon = item . name . endsWith ( '.tsx' ) ? 'fab fa-react' : 'fas fa-file' ;
61+ return (
62+ < div
63+ key = { index }
64+ className = { `${ active === item . id ? 'theme-bg-bg1' : '' } cursor-pointer flex items-center` }
65+ style = { { paddingLeft : `${ left } px` } }
66+ onClick = { ( ) => open ( item . id ) }
67+ >
68+ < i className = { `inline-block px-fs-10 px-mr-5 ${ icon } ` } > </ i >
69+ { item . name }
70+ </ div >
71+ ) ;
72+ } ) }
73+ </ div >
74+ ) ;
75+ } ;
76+
77+ export function EditorTabs ( props : EditorTabsProps ) {
78+ const { active, files, open } = props ;
79+ return (
80+ < div className = "flex px-pt-5 px-px-3" >
81+ { files . filter ( item => item . type === 'file' ) . map ( ( item , index ) => {
82+ const icon = item . name . endsWith ( '.tsx' ) ? 'fab fa-react' : 'fas fa-file' ;
83+ return (
84+ < div
85+ key = { `tab-${ index } ` }
86+ className = { `${ active === item . id ? 'bg-black text-white' : 'theme-bg-bg1' } px-mr-3 px-py-5 px-px-16 inline-block whitespace-nowrap cursor-pointer` }
87+ onClick = { ( ) => open ( item . id ) }
88+ >
89+ < i className = { `inline-block px-fs-10 px-mr-5 ${ icon } ` } > </ i >
90+ { item . name }
91+ </ div >
92+ ) ;
93+ } ) }
94+ </ div >
95+ ) ;
96+ } ;
97+
98+ export function EditorFiles ( props : EditorFilesProps ) {
99+ const { active, className = '' , files } = props ;
100+ return (
101+ < >
102+ { files . filter ( item => item . type === 'file' ) . map ( ( item , index ) => {
103+ return (
104+ < Code numbers copy
105+ key = { `file-${ index } ` }
106+ language = "javascript"
107+ onCopy = { ( ) => notify ( 'success' , 'Copied to clipboard' ) }
108+ className = { `${ active !== item . id ? 'hidden' : '' } rsm-px-l-0 bg-black text-white overflow-auto !absolute px-r-0 px-b-0 px-t-34 ${ className } ` }
109+ > { item . content } </ Code >
110+ ) ;
111+ } ) }
112+ </ >
113+ ) ;
114+ } ;
115+
116+ export default function Editor ( props : EditorProps ) {
117+ const {
118+ title = 'PROJECT' ,
119+ files = [ ] ,
120+ value,
121+ className = '' ,
122+ leftClassName = '' ,
123+ topClassName = '' ,
124+ mainClassName = ''
125+ } = props ;
126+ const [ file , open ] = useState ( value ) ;
127+ return (
128+ < div className = { `relative ${ className } ` } >
129+ < div className = { `theme-bg-bg2 px-lh-30 absolute px-t-0 px-b-0 flex flex-col rsm-hidden ${ leftClassName } ` } >
130+ < div className = "px-p-5" > { title } </ div >
131+ < EditorExplorer active = { file } files = { files } open = { open } />
132+ </ div >
133+ < div className = { `theme-bg-bg3 overflow-x-auto absolute px-r-0 px-t-0 px-h-34 rsm-px-l-0 ${ topClassName } ` } >
134+ < EditorTabs active = { file } files = { files } open = { open } />
135+ </ div >
136+ < EditorFiles className = { mainClassName } active = { file } files = { files } />
137+ </ div >
138+ ) ;
139+ }
0 commit comments