145 lines
6.3 KiB
Vue
145 lines
6.3 KiB
Vue
<template>
|
|
<nav v-if="!advanced" aria-label="Generation type" class="grid grid-cols-3 gap-2 rounded-2xl border border-white/10 bg-zinc-950/50 p-2">
|
|
<button v-for="kind in ['image', 'video'] as const" :key="kind" type="button" :aria-pressed="current === kind" class="rounded-xl px-3 py-3 font-semibold capitalize" :class="current === kind ? 'bg-amber-400 text-zinc-950' : 'text-zinc-300 hover:bg-white/5'" @click="emit('select', kind)">{{ kind }}</button>
|
|
<NuxtLink to="/music?engine=yue2" class="rounded-xl px-3 py-3 text-center font-semibold" :aria-current="current === 'music' ? 'page' : undefined" :class="current === 'music' ? 'bg-amber-400 text-zinc-950' : 'text-zinc-300 hover:bg-white/5'">Music</NuxtLink>
|
|
</nav>
|
|
<div v-else class="mb-4 grid grid-cols-3 gap-3">
|
|
<div
|
|
class="overflow-hidden rounded-3xl border transition"
|
|
:class="current === 'video' ? 'border-amber-300 bg-amber-400/10 text-amber-50' : 'border-white/10 text-zinc-400'"
|
|
>
|
|
<button
|
|
type="button"
|
|
class="w-full px-4 pb-3 pt-4 text-left transition"
|
|
:class="current === 'video' ? '' : 'hover:text-zinc-200'"
|
|
@click="emit('select', 'video')"
|
|
>
|
|
<svg class="h-10 w-10" viewBox="0 0 40 40" fill="none" aria-hidden="true">
|
|
<rect x="4" y="10" width="24" height="20" rx="3" stroke="currentColor" stroke-width="2" />
|
|
<path d="M28 16 36 12v16l-8-4V16Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
<circle cx="12" cy="20" r="2" fill="currentColor" />
|
|
</svg>
|
|
<span class="mt-3 block font-display text-lg font-bold text-zinc-100">Video</span>
|
|
</button>
|
|
<div v-if="ltxEnabled" class="grid grid-cols-2 border-t border-white/10">
|
|
<button
|
|
type="button"
|
|
class="border-r border-white/10 px-3 py-2.5 text-left text-sm transition"
|
|
:class="engineBtnClass(current === 'video' && videoEngine === 'minimax')"
|
|
@click="pickVideo('minimax')"
|
|
>
|
|
<span class="block font-semibold">MiniMax</span>
|
|
<span class="text-xs opacity-80">H3</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="px-3 py-2.5 text-left text-sm transition"
|
|
:class="engineBtnClass(current === 'video' && videoEngine === 'ltx')"
|
|
@click="pickVideo('ltx')"
|
|
>
|
|
<span class="block font-semibold">LTX</span>
|
|
<span class="text-xs opacity-80">2.3</span>
|
|
</button>
|
|
</div>
|
|
<p v-else class="border-t border-white/10 px-4 py-2 text-xs text-zinc-500">MiniMax H3</p>
|
|
<p class="border-t border-white/10 px-4 py-2 text-xs text-zinc-400">{{ videoStart === 'still' ? 'Image to video' : 'Text to video' }} · automatic</p>
|
|
</div>
|
|
|
|
<div
|
|
class="overflow-hidden rounded-3xl border transition"
|
|
:class="current === 'image' ? 'border-amber-300 bg-amber-400/10 text-amber-50' : 'border-white/10 text-zinc-400'"
|
|
>
|
|
<button
|
|
type="button"
|
|
class="w-full px-4 pb-3 pt-4 text-left transition"
|
|
:class="current === 'image' ? '' : 'hover:text-zinc-200'"
|
|
@click="emit('select', 'image')"
|
|
>
|
|
<svg class="h-10 w-10" viewBox="0 0 40 40" fill="none" aria-hidden="true">
|
|
<rect x="6" y="8" width="28" height="24" rx="3" stroke="currentColor" stroke-width="2" />
|
|
<path d="m10 26 7-8 6 7 3-3 4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
<circle cx="15" cy="15" r="2.5" fill="currentColor" />
|
|
</svg>
|
|
<span class="mt-3 block font-display text-lg font-bold text-zinc-100">Image</span>
|
|
</button>
|
|
<div class="grid grid-cols-2 border-t border-white/10">
|
|
<button
|
|
type="button"
|
|
class="border-r border-white/10 px-3 py-2.5 text-left text-sm transition"
|
|
:class="engineBtnClass(current === 'image' && imageEngine === 'flux')"
|
|
@click="pickImage('flux')"
|
|
>
|
|
<span class="block font-semibold">Flux</span>
|
|
<span class="text-xs opacity-80">Klein 9B</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="px-3 py-2.5 text-left text-sm transition"
|
|
:class="engineBtnClass(current === 'image' && imageEngine === 'krea')"
|
|
@click="pickImage('krea')"
|
|
>
|
|
<span class="block font-semibold">Krea</span>
|
|
<span class="text-xs opacity-80">2 Turbo</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="overflow-hidden rounded-3xl border transition"
|
|
:class="current === 'music' ? 'border-amber-300 bg-amber-400/10 text-amber-50' : 'border-white/10 text-zinc-400'"
|
|
>
|
|
<NuxtLink
|
|
to="/music?engine=yue2"
|
|
class="block w-full px-4 pb-3 pt-4 text-left transition"
|
|
:class="current === 'music' ? '' : 'hover:text-zinc-200'"
|
|
>
|
|
<svg class="h-10 w-10" viewBox="0 0 40 40" fill="none" aria-hidden="true">
|
|
<circle cx="20" cy="20" r="12" stroke="currentColor" stroke-width="2" />
|
|
<path d="M18 14v12l10-4V12l-10 2Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
</svg>
|
|
<span class="mt-3 block font-display text-lg font-bold text-zinc-100">Music</span>
|
|
</NuxtLink>
|
|
<p class="border-t border-white/10 px-4 py-2 text-xs text-zinc-400">YuE2 · 3B lyrics-to-song</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const props = withDefaults(defineProps<{
|
|
current: 'video' | 'image' | 'music'
|
|
advanced?: boolean
|
|
ltxEnabled?: boolean
|
|
videoEngine?: 'minimax' | 'ltx'
|
|
videoStart?: 'still' | 'text'
|
|
imageEngine?: 'flux' | 'krea'
|
|
musicEngine?: 'yue2'
|
|
}>(), {
|
|
ltxEnabled: false,
|
|
videoEngine: 'minimax',
|
|
videoStart: 'still',
|
|
imageEngine: 'flux',
|
|
musicEngine: 'yue2'
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
select: [kind: 'video' | 'image']
|
|
'video-engine': [engine: 'minimax' | 'ltx']
|
|
'image-engine': [engine: 'flux' | 'krea']
|
|
}>()
|
|
|
|
function engineBtnClass(active: boolean) {
|
|
if (active) return 'bg-amber-400/15 text-amber-100'
|
|
return 'text-zinc-400 hover:bg-white/5 hover:text-zinc-200'
|
|
}
|
|
|
|
function pickVideo(engine: 'minimax' | 'ltx') {
|
|
emit('video-engine', engine)
|
|
if (props.current !== 'video') emit('select', 'video')
|
|
}
|
|
|
|
function pickImage(engine: 'flux' | 'krea') {
|
|
emit('image-engine', engine)
|
|
if (props.current !== 'image') emit('select', 'image')
|
|
}
|
|
</script>
|