Skip to content

Commit

Permalink
feat(playground): 支持 NutUI 版本切换 (#2504)
Browse files Browse the repository at this point in the history
  • Loading branch information
eiinu authored Aug 27, 2023
1 parent 51ef413 commit 5ed04fd
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 14 deletions.
51 changes: 48 additions & 3 deletions packages/nutui-playground/src/Header.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
<script setup lang="ts">
import { ref } from 'vue';
import { downloadProject } from './download/download';
import Sun from './icons/Sun.vue';
import Moon from './icons/Moon.vue';
import Share from './icons/Share.vue';
import Download from './icons/Download.vue';
import GitHub from './icons/GitHub.vue';
import type { ReplStore } from '@vue/repl';
import VersionSelect from './VersionSelect.vue';
import type { NutUIStore } from './store';
const props = defineProps<{
store: ReplStore;
store: NutUIStore;
}>();
const nutuiVersion = ref(`latest`);
const { store } = props;
async function setNutUIVersion(v: string) {
nutuiVersion.value = `loading...`;
props.store.setNutUIVersion(v);
nutuiVersion.value = `v${v}`;
}
async function copyLink() {
await navigator.clipboard.writeText(location.href);
Expand All @@ -35,6 +42,13 @@ function toggleDark() {
<span>NutUI Playground</span>
</h1>
<div class="links">
<VersionSelect
:model-value="nutuiVersion"
@update:model-value="setNutUIVersion"
pkg="@nutui/nutui"
label="NutUI Version"
>
</VersionSelect>
<button title="Toggle dark mode" class="toggle-dark" @click="toggleDark">
<Sun class="light" />
<Moon class="dark" />
Expand Down Expand Up @@ -140,6 +154,37 @@ h1 img {
color: var(--highlight);
}
.versions {
display: none;
position: absolute;
left: 40px;
top: 40px;
background-color: var(--bg-light);
border: 1px solid var(--border);
border-radius: 4px;
list-style-type: none;
padding: 8px;
margin: 0;
max-height: calc(100vh - 70px);
overflow: scroll;
}
.versions a {
display: block;
padding: 6px 12px;
text-decoration: none;
cursor: pointer;
color: var(--base);
}
.versions a:hover {
color: var(--green);
}
.versions.expanded {
display: block;
}
.links > * {
display: flex;
align-items: center;
Expand Down
96 changes: 96 additions & 0 deletions packages/nutui-playground/src/VersionSelect.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const expanded = ref(false);
const versions = ref<string[]>();
const props = defineProps<{
pkg: string;
label: string;
modelValue: string;
}>();
const emits = defineEmits(['update:modelValue']);
async function toggle() {
expanded.value = !expanded.value;
if (!versions.value) {
versions.value = await fetchVersions();
}
}
async function fetchVersions(): Promise<string[]> {
const res = await fetch(`https://data.jsdelivr.com/v1/package/npm/${props.pkg}`);
const { versions } = (await res.json()) as { versions: string[] };
if (props.pkg === '@nutui/nutui') {
const filteredVersions = (versions as any).filter((i) => {
return !i.includes('-') && i >= '4.1.0';
});
return filteredVersions;
}
return versions;
}
function setVersion(v: string) {
emits('update:modelValue', v);
expanded.value = false;
}
onMounted(() => {
window.addEventListener('click', () => {
expanded.value = false;
});
window.addEventListener('blur', () => {
if (document.activeElement?.tagName === 'IFRAME') {
expanded.value = false;
}
});
});
</script>

<template>
<div class="version" @click.stop>
<span class="active-version" @click="toggle">
{{ label }}
<span class="number">{{ props.modelValue }}</span>
</span>

<ul class="versions" :class="{ expanded }">
<li v-if="!versions"><a>loading versions...</a></li>
<li v-for="version of versions" :key="version">
<a @click="setVersion(version)">v{{ version }}</a>
</li>
<div @click="expanded = false">
<slot />
</div>
</ul>
</div>
</template>

<style>
.version {
margin-right: 12px;
position: relative;
}
.active-version {
cursor: pointer;
position: relative;
display: inline-flex;
place-items: center;
}
.active-version .number {
color: var(--green);
margin-left: 4px;
}
.active-version::after {
content: '';
width: 0;
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 6px solid #aaa;
margin-left: 8px;
}
</style>
7 changes: 3 additions & 4 deletions packages/nutui-playground/src/download/template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
},
"dependencies": {
"vue": "^3.3.4",
"@nutui/nutui": "^4.0.12",
"@nutui/nutui": "^4.1.0",
"@nutui/touch-emulator": "^1.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"@vue/compiler-sfc": "^3.3.4",
"vite": "^4.3.9",
"@vitejs/plugin-vue": "^4.3.3",
"vite": "^4.4.9",
"unplugin-vue-components": "^0.25.1"
}
}
34 changes: 27 additions & 7 deletions packages/nutui-playground/src/store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StoreOptions, File, ReplStore } from '@vue/repl';
import { StoreOptions, File, ReplStore, compileFile } from '@vue/repl';
import { ref, computed } from 'vue';

const style = 'https://cdn.jsdelivr.net/npm/@nutui/nutui@latest/dist/style.css';
const style = ref('https://cdn.jsdelivr.net/npm/@nutui/nutui@latest/dist/style.css');

const appFileCode = `
<script setup lang="ts">
Expand Down Expand Up @@ -38,8 +39,8 @@ installNutUI()
<App />
</template>
`;
const installCode = `
import NutUI from '@nutui/nutui'
const installCode = computed(
() => `import NutUI from '@nutui/nutui'
import { getCurrentInstance } from 'vue'
const appendStyle = () => {
Expand All @@ -50,7 +51,7 @@ const appendStyle = () => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = '${style}'
link.href = '${style.value}'
link.onload = resolve
link.onerror = reject
document.body.appendChild(link)
Expand All @@ -63,7 +64,8 @@ export const installNutUI = () => {
const instance = getCurrentInstance()
instance.appContext.app.use(NutUI)
}
`;
`
);

const utoa = (data: string) => {
return btoa(unescape(encodeURIComponent(data)));
Expand Down Expand Up @@ -93,7 +95,7 @@ export class NutUIStore extends ReplStore {

const container = new File(CONTAINER_FILE, containerCode, true);
this.addFile(container);
const install = new File(INSTALL_FILE, installCode, true);
const install = new File(INSTALL_FILE, installCode.value, true);
this.addFile(install);

this.state.mainFile = CONTAINER_FILE;
Expand All @@ -107,4 +109,22 @@ export class NutUIStore extends ReplStore {
delete files[INSTALL_FILE.replace('src/', '')];
return '#' + utoa(JSON.stringify(files));
}
setNutUIVersion(v: string) {
style.value = `https://cdn.jsdelivr.net/npm/@nutui/nutui@${v}/dist/style.css`;
const install = new File(INSTALL_FILE, installCode.value, true);
this.addFile(install);
compileFile(this, install).then((errs) => this.state.errors.push(...errs));
this.setImportMap({
imports: {
'@nutui/nutui': `https://cdn.jsdelivr.net/npm/@nutui/nutui@${v}/dist/nutui.js`,
'@nutui/icons-vue': 'https://cdn.jsdelivr.net/npm/@nutui/icons-vue@latest/dist/lib/index.mjs',
'@nutui/touch-emulator': 'https://cdn.jsdelivr.net/npm/@nutui/touch-emulator',
// compatible with Functional Component style import
'@nutui/nutui/dist/packages/toast/style': './style.js',
'@nutui/nutui/dist/packages/dialog/style': './style.js',
'@nutui/nutui/dist/packages/imagepreview/style': './style.js',
'@nutui/nutui/dist/packages/notify/style': './style.js'
}
});
}
}

0 comments on commit 5ed04fd

Please sign in to comment.