kt-template-online-playground/src/output/Output.vue
2026-05-08 14:30:56 +08:00

131 lines
2.9 KiB
Vue

<script setup lang="ts">
import Preview from './Preview.vue'
import SsrOutput from './SsrOutput.vue'
import { computed, inject, useTemplateRef, watchEffect } from 'vue'
import {
type EditorComponentType,
type OutputModes,
injectKeyProps,
} from '../types'
const props = defineProps<{
editorComponent: EditorComponentType
showCompileOutput?: boolean
showOpenSourceMap?: boolean
showSsrOutput?: boolean
ssr: boolean
}>()
const { store } = inject(injectKeyProps)!
const previewRef = useTemplateRef('preview')
const modes = computed(() => {
const outputModes: OutputModes[] = ['preview']
if (props.showCompileOutput) {
outputModes.push('js', 'css', 'ssr')
}
if (props.ssr && props.showSsrOutput) {
outputModes.push('ssr output')
}
return outputModes
})
const mode = computed<OutputModes>({
get: () => store.value.outputMode,
set: (value) => (store.value.outputMode = value),
})
watchEffect(() => {
if (!modes.value.includes(mode.value)) {
mode.value = modes.value[0]
}
})
const showSourceMap = computed(() => {
return props.showOpenSourceMap && (mode.value === 'js' || mode.value === 'ssr')
})
function openSourceMap() {
const { clientMap, ssrMap } = store.value.activeFile.compiled
window.open(mode.value === 'js' ? clientMap : ssrMap)
}
function reload() {
previewRef.value?.reload()
}
defineExpose({ reload, previewRef })
</script>
<template>
<div class="tab-buttons">
<button
v-for="m of modes"
:key="m"
:class="{ active: mode === m }"
@click="mode = m"
>
<span>{{ m }}</span>
</button>
</div>
<div class="output-container">
<Preview ref="preview" :show="mode === 'preview'" :ssr="ssr" />
<SsrOutput
v-if="mode === 'ssr output'"
:context="store.ssrOutput.context"
:html="store.ssrOutput.html"
/>
<props.editorComponent
v-else-if="mode !== 'preview'"
readonly
:filename="store.activeFile.filename"
:value="store.activeFile.compiled[mode]"
:mode="mode"
/>
</div>
<div v-if="showSourceMap" class="tab-buttons open-sourcemap">
<button>
<span @click="openSourceMap">open sourceMap</span>
</button>
</div>
</template>
<style scoped>
.output-container {
height: calc(100% - var(--header-height));
overflow: hidden;
position: relative;
}
.tab-buttons {
box-sizing: border-box;
border-bottom: 1px solid var(--border);
background-color: var(--bg);
height: var(--header-height);
overflow: hidden;
}
.tab-buttons button {
padding: 0;
box-sizing: border-box;
}
.tab-buttons span {
font-size: 13px;
font-family: var(--font-code);
text-transform: uppercase;
color: var(--text-light);
display: inline-block;
padding: 8px 16px 6px;
line-height: 20px;
}
button.active {
color: var(--color-branding-dark);
border-bottom: 3px solid var(--color-branding-dark);
}
.open-sourcemap {
position: absolute;
right: 0;
top: 0;
}
</style>