@@ -13,6 +13,7 @@ import {
13
13
SelectTrigger ,
14
14
SelectValue ,
15
15
} from '@/components/ui/select' ;
16
+ import { Skeleton } from '@/components/ui/skeleton' ;
16
17
import { getTheme , type IEditorTheme , languages , themeOptions } from '@/lib/editor/extensions' ;
17
18
import { useCollab } from '@/lib/hooks/use-collab' ;
18
19
@@ -26,67 +27,81 @@ type EditorProps = {
26
27
export const Editor = ( { room } : EditorProps ) => {
27
28
const { height } = useWindowSize ( ) ;
28
29
const [ theme , setTheme ] = useState < IEditorTheme > ( 'vscodeDark' ) ;
29
- const { editorRef, extensions, language, setLanguage, code, setCode, members } = useCollab ( room ) ;
30
+ const { editorRef, extensions, language, setLanguage, code, setCode, members, isLoading } =
31
+ useCollab ( room ) ;
30
32
const themePreset = useMemo ( ( ) => {
31
33
return getTheme ( theme ) ;
32
34
} , [ theme ] ) ;
33
35
34
36
return (
35
37
< div className = 'flex flex-col gap-4 p-4' >
36
- < div className = 'flex w-full justify-between gap-4' >
37
- < div className = 'flex gap-4' >
38
- < div className = 'flex flex-col gap-2' >
39
- < Label > Language</ Label >
40
- < Select value = { language } onValueChange = { ( val ) => setLanguage ( val as LanguageName ) } >
41
- < SelectTrigger className = 'max-w-[150px]' >
42
- < SelectValue />
43
- </ SelectTrigger >
44
- < SelectContent >
45
- { languages . map ( ( lang , idx ) => (
46
- < SelectItem value = { lang } key = { idx } >
47
- { lang }
48
- </ SelectItem >
49
- ) ) }
50
- </ SelectContent >
51
- </ Select >
38
+ { isLoading ? (
39
+ < div className = 'flex h-16 w-full flex-row justify-between pt-4' >
40
+ < div className = 'flex h-10 flex-row gap-4' >
41
+ < Skeleton className = 'h-10 w-16' />
42
+ < Skeleton className = 'h-10 w-32' />
52
43
</ div >
53
- < div className = 'flex flex-col gap-2' >
54
- < Label > Theme</ Label >
55
- < Select value = { theme } onValueChange = { ( val ) => setTheme ( val as IEditorTheme ) } >
56
- < SelectTrigger className = 'max-w-[150px]' >
57
- < SelectValue />
58
- </ SelectTrigger >
59
- < SelectContent >
60
- { themeOptions . map ( ( theme , idx ) => (
61
- < SelectItem value = { theme } key = { idx } >
62
- { theme }
63
- </ SelectItem >
64
- ) ) }
65
- </ SelectContent >
66
- </ Select >
44
+ < div className = 'flex flex-row items-center gap-2' >
45
+ < Skeleton className = 'size-10 rounded-full' />
46
+ < Skeleton className = 'h-8 w-24' />
67
47
</ div >
68
48
</ div >
69
- < div className = 'flex items-center gap-2' >
70
- < div className = 'flex gap-1 font-mono text-xs' >
71
- { /* TODO: Get user avatar and display */ }
72
- { members . map ( ( member , index ) => (
73
- < div
74
- className = 'grid size-8 place-items-center !overflow-clip rounded-full border p-1 text-xs'
75
- style = { {
76
- borderColor : member . color ,
77
- } }
78
- key = { index }
79
- >
80
- < span className = 'translate-x-[calc(-50%+12px)]' > { member . userId } </ span >
81
- </ div >
82
- ) ) }
49
+ ) : (
50
+ < div className = 'flex w-full justify-between gap-4' >
51
+ < div className = 'flex gap-4' >
52
+ < div className = 'flex flex-col gap-2' >
53
+ < Label > Language</ Label >
54
+ < Select value = { language } onValueChange = { ( val ) => setLanguage ( val as LanguageName ) } >
55
+ < SelectTrigger className = 'max-w-[150px]' >
56
+ < SelectValue />
57
+ </ SelectTrigger >
58
+ < SelectContent >
59
+ { languages . map ( ( lang , idx ) => (
60
+ < SelectItem value = { lang } key = { idx } >
61
+ { lang }
62
+ </ SelectItem >
63
+ ) ) }
64
+ </ SelectContent >
65
+ </ Select >
66
+ </ div >
67
+ < div className = 'flex flex-col gap-2' >
68
+ < Label > Theme</ Label >
69
+ < Select value = { theme } onValueChange = { ( val ) => setTheme ( val as IEditorTheme ) } >
70
+ < SelectTrigger className = 'max-w-[150px]' >
71
+ < SelectValue />
72
+ </ SelectTrigger >
73
+ < SelectContent >
74
+ { themeOptions . map ( ( theme , idx ) => (
75
+ < SelectItem value = { theme } key = { idx } >
76
+ { theme }
77
+ </ SelectItem >
78
+ ) ) }
79
+ </ SelectContent >
80
+ </ Select >
81
+ </ div >
82
+ </ div >
83
+ < div className = 'flex items-center gap-2' >
84
+ < div className = 'flex gap-1 font-mono text-xs' >
85
+ { /* TODO: Get user avatar and display */ }
86
+ { members . map ( ( member , index ) => (
87
+ < div
88
+ className = 'grid size-8 place-items-center !overflow-clip rounded-full border p-1 text-xs'
89
+ style = { {
90
+ borderColor : member . color ,
91
+ } }
92
+ key = { index }
93
+ >
94
+ < span className = 'translate-x-[calc(-50%+12px)]' > { member . userId } </ span >
95
+ </ div >
96
+ ) ) }
97
+ </ div >
98
+ < Button variant = 'destructive' size = 'sm' className = 'group flex items-center !px-2 !py-1' >
99
+ < ChevronLeftIcon className = 'transition-transform duration-200 ease-in-out group-hover:-translate-x-px' />
100
+ < span > Disconnect</ span >
101
+ </ Button >
83
102
</ div >
84
- < Button variant = 'destructive' size = 'sm' className = 'group flex items-center !px-2 !py-1' >
85
- < ChevronLeftIcon className = 'transition-transform duration-200 ease-in-out group-hover:-translate-x-px' />
86
- < span > Disconnect</ span >
87
- </ Button >
88
103
</ div >
89
- </ div >
104
+ ) }
90
105
< div className = 'border-border w-full !overflow-clip rounded-lg border shadow-sm' >
91
106
< CodeMirror
92
107
ref = { editorRef }
0 commit comments