33import { Repl } from ' @vue/repl'
44import Monaco from ' @vue/repl/monaco-editor'
55import { useStore } from ' ./composables/store'
6+ import { useConsole } from ' ./composables/use-console'
67
78const loading = ref (true )
89const replRef = ref <InstanceType <typeof Repl >>()
10+ const showConsole = useLocalStorage (' console-visible' , false )
11+ const consoleHeight = useLocalStorage (' console-height' , 200 )
12+ const { logs, clearLogs } = useConsole ()
913
1014const AUTO_SAVE_KEY = ' auto-save-state'
1115function getAutoSaveState() {
@@ -18,6 +22,7 @@ function setAutoSaveState(value: boolean) {
1822const autoSave = ref (getAutoSaveState ())
1923
2024const previewOptions = {
25+ showRuntimeError: false ,
2126 headHTML: `
2227 <script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"><\/ script>
2328 <script>
@@ -92,16 +97,26 @@ const handleKeydown = (evt: KeyboardEvent) => {
9297 }
9398}
9499
95- // persist state
96- watchEffect (() =>
100+ useEventListener (window , ' keydown' , (evt : KeyboardEvent ) => {
101+ if ((evt .ctrlKey || evt .metaKey ) && evt .code === ' Backquote' ) {
102+ evt .preventDefault ()
103+ showConsole .value = ! showConsole .value
104+ }
105+ })
106+
107+ // persist state & clear console on file changes
108+ watchEffect (() => {
109+ const serialized = store .serialize ()
97110 history .replaceState (
98111 {},
99112 ' ' ,
100- ` ${location .origin }${location .pathname }#${store .serialize ()} ` ,
101- ),
102- )
113+ ` ${location .origin }${location .pathname }#${serialized } ` ,
114+ )
115+ clearLogs ()
116+ })
103117
104118const refreshPreview = () => {
119+ clearLogs ()
105120 replRef .value ?.reload ()
106121}
107122
@@ -110,7 +125,12 @@ watch(autoSave, setAutoSaveState)
110125
111126<template >
112127 <div v-if =" !loading" antialiased >
113- <Header :store =" store" @refresh =" refreshPreview" />
128+ <Header
129+ :store =" store"
130+ :show-console =" showConsole"
131+ @refresh =" refreshPreview"
132+ @toggle-console =" showConsole = !showConsole"
133+ />
114134 <Repl
115135 ref =" replRef"
116136 v-model =" autoSave"
@@ -119,9 +139,16 @@ watch(autoSave, setAutoSaveState)
119139 :store =" store"
120140 :editor =" Monaco"
121141 :preview-options =" previewOptions"
122- :clear-console =" false"
123142 @keydown =" handleKeydown"
124143 />
144+ <Teleport defer to =" .vue-repl .right" >
145+ <ConsolePanel
146+ v-if =" showConsole"
147+ v-model:height =" consoleHeight"
148+ :logs =" logs"
149+ @clear =" clearLogs"
150+ />
151+ </Teleport >
125152 </div >
126153 <template v-else >
127154 <div v-loading =" { text: 'Loading...' }" h-100vh />
@@ -142,6 +169,21 @@ body {
142169 height : calc (100vh - var (--nav-height )) !important ;
143170}
144171
172+ .vue-repl .right {
173+ display : flex !important ;
174+ flex-direction : column !important ;
175+ }
176+
177+ .vue-repl .right > .tab-buttons {
178+ flex-shrink : 0 ;
179+ }
180+
181+ .vue-repl .right > .output-container {
182+ flex : 1 ;
183+ height : auto !important ;
184+ min-height : 0 ;
185+ }
186+
145187.dark .vue-repl ,
146188.vue-repl {
147189 --color-branding : var (--el-color-primary ) !important ;
0 commit comments