diff --git a/app/components/ReplEditor.vue b/app/components/ReplEditor.vue new file mode 100644 index 0000000..3b05c50 --- /dev/null +++ b/app/components/ReplEditor.vue @@ -0,0 +1,45 @@ +<script setup lang="ts"> +import type { Store } from '@vue/repl' +import { Repl } from '@vue/repl' +import MonacoEditor from '@vue/repl/monaco-editor' + +const props = defineProps({ + ssr: { + type: Boolean, + default: false, + }, + store: { + type: Object as PropType<Store>, + required: true, + }, +}) + +const colorMode = useColorMode() + +const theme = computed(() => { + if (colorMode.value === 'dark') + return 'dark' + else + return 'light' +}) + +const previewOptions = { + headHTML: ` + <script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"><\/script> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css" /> + <script> + window.__unocss = { + rules: [], + presets: [], + } + <\/script> + `, +} +</script> + +<template> + <Repl + :store="props.store" :editor="MonacoEditor" :show-compile-output="true" :theme="theme" :preview-theme="true" + :preview-options="previewOptions" :ssr="props.ssr" + /> +</template> diff --git a/app/layouts/default.vue b/app/layouts/default.vue index f5236a5..f5a446b 100644 --- a/app/layouts/default.vue +++ b/app/layouts/default.vue @@ -2,26 +2,21 @@ import { getVersionsBatch } from 'fast-npm-meta' import semver from 'semver' -// todo: type -const versions = useSessionStorage<any>('versions', []) - -const loadingVersions = shallowRef(false) - -async function fetchVersions() { - loadingVersions.value = true - versions.value = await getVersionsBatch(['@vueuse/core', 'vue']) - loadingVersions.value = false -} - -if (!versions.value.length) { - fetchVersions() -} +const { data: versions, status, error, refresh: fetchVersions } = await useAsyncData( + 'versions', + async () => getVersionsBatch(['@vueuse/core', 'vue']), + { default: () => ([]) }, +) + +const loadingVersions = computed(() => { + return status.value === 'pending' +}) const vueVersion = shallowRef() const vueVersions = computed(() => { const vue = versions.value.find(p => p.name === 'vue') - if (vue?.error) + if (vue?.error || error.value) return [] return vue?.versions ?? [] }) @@ -32,7 +27,7 @@ const vueUseVersion = useRouteQuery('vueuse', 'latest') const vueUseVersions = computed(() => { const vueuse = versions.value.find(p => p.name === '@vueuse/core') - if (vueuse?.error) + if (vueuse?.error || error.value) return [] return vueuse?.versions ?? [] }) @@ -68,7 +63,7 @@ const prod = useRouteQuery<string, boolean>('prod', 'false', { <USwitch v-model="prod" label="Prod" /> <USelectMenu v-model="vueUseVersion" :items="vueUseVersionsSorted" class="w-32" icon="i-logos-vueuse" :loading="loadingVersions" /> <USelectMenu v-model="vueVersion" :items="vueVersionsSorted" class="w-32" icon="i-logos-vue" :loading="loadingVersions" /> - <UButton icon="i-lucide-refresh-ccw" size="md" color="primary" variant="soft" @click="fetchVersions" /> + <UButton icon="i-lucide-refresh-ccw" size="md" color="primary" variant="soft" @click="() => fetchVersions()" /> <UButton color="neutral" variant="ghost" :icon="colorMode.preference === 'dark' ? 'i-heroicons-moon' : 'i-heroicons-sun'" diff --git a/app/pages/index.vue b/app/pages/index.vue index 340c760..89125a0 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -1,8 +1,7 @@ <script setup lang="ts"> import type { OutputModes } from '@vue/repl' import type { ShallowRef } from 'vue' -import { mergeImportMap, Repl, useStore, useVueImportMap } from '@vue/repl' -import MonacoEditor from '@vue/repl/monaco-editor' +import { mergeImportMap, useStore, useVueImportMap } from '@vue/repl' const showOutput = useRouteQuery<string, boolean>('showOutput', 'false', { transform: stringToBooleanTransformer, @@ -81,35 +80,15 @@ watch(() => injectedVueVersion.value, (newVersion) => { watch(() => prod.value, (newProd) => { productionMode.value = newProd }, { immediate: true }) - -const colorMode = useColorMode() - -const theme = computed(() => { - if (colorMode.value === 'dark') - return 'dark' - else - return 'light' -}) - -const previewOptions = { - headHTML: ` - <script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"><\/script> - <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css" /> - <script> - window.__unocss = { - rules: [], - presets: [], - } - <\/script> - `, -} </script> <template> - <client-only> - <Repl - :store="store" :editor="MonacoEditor" :show-compile-output="true" :theme="theme" :preview-theme="true" - :preview-options="previewOptions" :ssr="ssr" - /> - </client-only> + <ClientOnly> + <ReplEditor :ssr="ssr" :store="store" /> + <template #fallback> + <div class="flex w-full h-full justify-center items-center px-12"> + <UProgress animation="swing" /> + </div> + </template> + </ClientOnly> </template> diff --git a/nuxt.config.ts b/nuxt.config.ts index b0befb6..b81e6ec 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,8 +1,8 @@ // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - ssr: false, compatibilityDate: '2024-11-01', devtools: { enabled: true }, + sourcemap: false, future: { compatibilityVersion: 4, }, @@ -18,9 +18,12 @@ export default defineNuxtConfig({ }, build: { rollupOptions: { - external: ['typescript'], + external: ['typescript', '@vue/compiler-sfc'], }, }, + ssr: { + noExternal: ['@vue/repl'], + }, }, css: ['~/assets/css/main.css'], })