feat(stage): custom primary colors (#53)
* feat(stage-ui): allow disable transitions * fix(stage-web): apply motion map from file * chore(stage-web): change icon * feat(stage): custom primary colors
This commit is contained in:
@@ -36,7 +36,7 @@ onTokenLiteral(async () => {
|
||||
<div flex-1 /> <!-- spacer -->
|
||||
<div
|
||||
ref="chatHistoryRef" v-auto-animate max-h="30vh" flex="~ col"
|
||||
scrollbar="~ w-2 track-color-transparent thumb-color-pink-300 rounded" h-full w-full overflow-scroll
|
||||
scrollbar="~ w-2 track-color-transparent thumb-color-primary-300 rounded" h-full w-full overflow-scroll
|
||||
>
|
||||
<div flex-1 /> <!-- spacer -->
|
||||
<div v-for="(message, index) in messages" :key="index" mb-2>
|
||||
@@ -61,14 +61,14 @@ onTokenLiteral(async () => {
|
||||
</div>
|
||||
<div v-if="message.role === 'assistant'" flex mr="12">
|
||||
<div
|
||||
flex="~ col" border="4 solid pink-200" shadow="md pink-200/50" min-w-20 rounded-lg px-2 py-1 h="fit"
|
||||
bg="pink-100"
|
||||
flex="~ col" border="4 solid primary-200" shadow="md primary-200/50" min-w-20 rounded-lg px-2 py-1 h="fit"
|
||||
bg="primary-100"
|
||||
>
|
||||
<div>
|
||||
<span text-xs text="pink-400/90" font-semibold class="inline hidden">Airi</span>
|
||||
<span text-xs text="primary-400/90" font-semibold class="inline hidden">Airi</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="message.content" class="markdown-content" text="xs pink-400"
|
||||
v-if="message.content" class="markdown-content" text="xs primary-400"
|
||||
v-html="process(message.content as string)"
|
||||
/>
|
||||
<div v-else i-eos-icons:three-dots-loading />
|
||||
|
||||
@@ -104,9 +104,9 @@ onMounted(() => {
|
||||
<BasicTextarea
|
||||
v-model="messageInput"
|
||||
:placeholder="t('stage.message')"
|
||||
border="solid 2 pink-100"
|
||||
text="pink-400 hover:pink-600 placeholder:pink-400 placeholder:hover:pink-600"
|
||||
bg="pink-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
border="solid 2 primary-100"
|
||||
text="primary-400 hover:primary-600 placeholder:primary-400 placeholder:hover:primary-600"
|
||||
bg="primary-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
w-full resize-none overflow-y-scroll rounded-l-xl p-2 font-medium outline-none
|
||||
transition="all duration-250 ease-in-out placeholder:all placeholder:duration-250 placeholder:ease-in-out"
|
||||
@submit="handleSend"
|
||||
@@ -114,9 +114,9 @@ onMounted(() => {
|
||||
</div>
|
||||
<div
|
||||
class="px-4 py-2.5"
|
||||
border="solid 2 pink-100 "
|
||||
text="lg pink-400 hover:pink-600 placeholder:pink-400 placeholder:hover:pink-600"
|
||||
bg="pink-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
border="solid 2 primary-100 "
|
||||
text="lg primary-400 hover:primary-600 placeholder:primary-400 placeholder:hover:primary-600"
|
||||
bg="primary-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
flex items-center justify-center rounded-r-xl
|
||||
@click="openSettings"
|
||||
>
|
||||
|
||||
@@ -64,7 +64,7 @@ const modeIndicatorClass = computed(() => {
|
||||
>
|
||||
<div class="absolute h-32 w-full flex items-center justify-center b-2 b-pink bg-white">
|
||||
<div class="wall absolute top-0 h-8" />
|
||||
<div class="absolute left-0 top-0 h-full w-full flex animate-flash animate-duration-5s animate-count-infinite items-center justify-center text-1.5rem text-pink-300 font-bold">
|
||||
<div class="text-primary-300 absolute left-0 top-0 h-full w-full flex animate-flash animate-duration-5s animate-count-infinite items-center justify-center text-1.5rem font-bold">
|
||||
DRAG HERE TO MOVE
|
||||
</div>
|
||||
<div class="wall absolute bottom-0 h-8" />
|
||||
@@ -113,7 +113,7 @@ const modeIndicatorClass = computed(() => {
|
||||
}
|
||||
|
||||
.wall {
|
||||
@apply text-pink-200;
|
||||
@apply text-primary-200;
|
||||
|
||||
--wall-width: 8px;
|
||||
animation: wall-move 1s linear infinite;
|
||||
|
||||
@@ -153,9 +153,9 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
<div>
|
||||
<div
|
||||
grid="~ cols-[140px_1fr]" my-2 items-center gap-1.5 rounded-lg
|
||||
bg="[#fff6fc]" px-2 py-1 text="pink-400"
|
||||
bg="[#fff6fc]" px-2 py-1 text="primary-400"
|
||||
>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.openai-base-url.label') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -166,7 +166,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
h-6 w-full rounded-md bg-transparent px-2 py-1 text-right font-mono outline-none
|
||||
>
|
||||
</div>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.openai-api-key.label') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -177,7 +177,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
h-6 w-full rounded-md bg-transparent px-2 py-1 text-right font-mono outline-none
|
||||
>
|
||||
</div>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.elevenlabs-api-key.label') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -188,7 +188,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
h-6 w-full rounded-md bg-transparent px-2 py-1 text-right font-mono outline-none
|
||||
>
|
||||
</div>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.language.title') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -204,7 +204,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.models') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -223,7 +223,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.voices') }}</span>
|
||||
</div>
|
||||
<div flex="~ row" w-full text="xs">
|
||||
@@ -257,9 +257,9 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
<div>
|
||||
<div
|
||||
grid="~ cols-[140px_1fr]" my-2 items-center gap-1.5 rounded-lg
|
||||
bg="[#fff6fc]" px-2 py-1 text="pink-400"
|
||||
bg="[#fff6fc]" px-2 py-1 text="primary-400"
|
||||
>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>{{ t('settings.viewer') }}</span>
|
||||
</div>
|
||||
<select
|
||||
@@ -281,16 +281,16 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
<div pb-2>
|
||||
<div
|
||||
grid="~ cols-[140px_1fr]" my-2 items-center gap-1.5 rounded-lg
|
||||
bg="[#fff6fc]" p-2 text="pink-400"
|
||||
bg="[#fff6fc]" p-2 text="primary-400"
|
||||
>
|
||||
<template v-for="shortcut in shortcuts" :key="shortcut.type">
|
||||
<span text="xs pink-500">
|
||||
<span text="xs primary-500">
|
||||
{{ t(shortcut.name) }}
|
||||
</span>
|
||||
<div
|
||||
class="shortcut-item flex items-center justify-end gap-x-2 px-2 py-0.5"
|
||||
:class="{ recording: recordingFor === shortcut.type }"
|
||||
text="xs pink-500"
|
||||
text="xs primary-500"
|
||||
cursor-pointer
|
||||
@click="startRecording(shortcut)"
|
||||
>
|
||||
@@ -300,7 +300,7 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
<div v-else class="pointer-events-none">
|
||||
{{ shortcut.shortcut }}
|
||||
</div>
|
||||
<div v-if="isConflict(shortcut)" text="xs pink-500" i-solar:danger-square-bold w-4 />
|
||||
<div v-if="isConflict(shortcut)" text="xs primary-500" i-solar:danger-square-bold w-4 />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -311,14 +311,14 @@ function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
<div pb-2>
|
||||
<div
|
||||
grid="~ cols-[140px_1fr]" my-2 items-center gap-1.5 rounded-lg
|
||||
bg="[#fff6fc]" p-2 text="pink-400" @click="handleQuit"
|
||||
bg="[#fff6fc]" p-2 text="primary-400" @click="handleQuit"
|
||||
>
|
||||
<div text="xs pink-500">
|
||||
<div text="xs primary-500">
|
||||
<span>
|
||||
{{ t('settings.quit') }}
|
||||
</span>
|
||||
</div>
|
||||
<div text="sm pink-500" text-right>
|
||||
<div text="sm primary-500" text-right>
|
||||
<div i-solar:exit-bold-duotone ml-auto />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSettings } from '@proj-airi/stage-ui/stores/settings'
|
||||
import { StageTransitionGroup } from '@proj-airi/ui-transitions'
|
||||
import { useDark } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { watch } from 'vue'
|
||||
import { onMounted, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView } from 'vue-router'
|
||||
|
||||
@@ -14,6 +14,14 @@ const isDark = useDark()
|
||||
watch(settings.language, () => {
|
||||
i18n.locale.value = settings.language.value
|
||||
})
|
||||
|
||||
watch(settings.themeColorsHue, () => {
|
||||
document.documentElement.style.setProperty('--theme-colors-hue', settings.themeColorsHue.value.toString())
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
document.documentElement.style.setProperty('--theme-colors-hue', settings.themeColorsHue.value.toString())
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -23,6 +31,7 @@ watch(settings.language, () => {
|
||||
tertiary-color="#121212"
|
||||
:colors="!isDark ? ['#FF57C8', '#946BFF', '#64BCFF', '#FFFFFF'] : ['#FF57C8', '#946BFF', '#64BCFF', '#121212']"
|
||||
:z-index="100"
|
||||
:disable-transitions="settings.disableTransitions.value"
|
||||
>
|
||||
<RouterView />
|
||||
</StageTransitionGroup>
|
||||
|
||||
@@ -11,11 +11,12 @@ https://www.magicpattern.design/tools/css-backgrounds
|
||||
*/
|
||||
.cross-background-container {
|
||||
background-color: #ffffff;
|
||||
--cross-color: oklch(0.95 0.06 var(--theme-colors-hue));
|
||||
background:
|
||||
radial-gradient(circle, transparent 20%, #ffffff 20%, #ffffff 80%, transparent 80%, transparent),
|
||||
radial-gradient(circle, transparent 20%, #ffffff 20%, #ffffff 80%, transparent 80%, transparent) 25px 25px,
|
||||
linear-gradient(#f4ebf1 2px, transparent 2px) 0 -1px,
|
||||
linear-gradient(90deg, #f4ebf1 2px, #ffffff 2px) -1px 0;
|
||||
linear-gradient(var(--cross-color) 2px, transparent 2px) 0 -1px,
|
||||
linear-gradient(90deg, var(--cross-color) 2px, #ffffff 2px) -1px 0;
|
||||
background-size:
|
||||
50px 50px,
|
||||
50px 50px,
|
||||
|
||||
@@ -17,7 +17,7 @@ const props = withDefaults(defineProps<WaveProps>(), {
|
||||
height: 40,
|
||||
amplitude: 14,
|
||||
waveLength: 250,
|
||||
fillColor: '#f8e8f2',
|
||||
fillColor: 'oklch(95% 0.10 var(--theme-colors-hue))',
|
||||
direction: 'down',
|
||||
animationSpeed: 50,
|
||||
})
|
||||
|
||||
@@ -120,15 +120,15 @@ onAfterSend(async () => {
|
||||
<fieldset flex="~ row" w-fit rounded-lg>
|
||||
<label
|
||||
:class="[
|
||||
tab === 'chat' ? 'bg-pink-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'chat' ? 'text-pink-500 dark:text-pink-500' : '',
|
||||
tab === 'chat' ? 'bg-primary-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'chat' ? 'text-primary-500 dark:text-primary-500' : '',
|
||||
]"
|
||||
flex="~ row"
|
||||
:checked="tab === 'chat'"
|
||||
:aria-checked="tab === 'chat'"
|
||||
border="solid l-2 t-2 b-2 pink-100 dark:[#3c2632]"
|
||||
bg="hover:pink-100 dark:hover:[#3c2632]"
|
||||
text="pink-300 hover:pink-500 dark:pink-300/50 dark:hover:pink-500"
|
||||
border="solid l-2 t-2 b-2 primary-100 dark:[#3c2632]"
|
||||
bg="hover:primary-100 dark:hover:[#3c2632]"
|
||||
text="primary-300 hover:primary-500 dark:primary-300/50 dark:hover:primary-500"
|
||||
transition="all duration-250 ease-in-out"
|
||||
cursor-pointer items-center gap-1 rounded-l-lg px-2
|
||||
>
|
||||
@@ -140,15 +140,15 @@ onAfterSend(async () => {
|
||||
</label>
|
||||
<label
|
||||
:class="[
|
||||
tab === 'custom' ? 'bg-pink-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'custom' ? 'text-pink-500 dark:text-pink-500' : '',
|
||||
tab === 'custom' ? 'bg-primary-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'custom' ? 'text-primary-500 dark:text-primary-500' : '',
|
||||
]"
|
||||
flex="~ row"
|
||||
:checked="tab === 'custom'"
|
||||
:aria-checked="tab === 'custom'"
|
||||
border="solid t-2 b-2 pink-100 dark:[#3c2632]"
|
||||
bg="hover:pink-100 dark:hover:[#3c2632]"
|
||||
text="pink-300 hover:pink-500 dark:pink-300/50 dark:hover:pink-500"
|
||||
border="solid t-2 b-2 primary-100 dark:[#3c2632]"
|
||||
bg="hover:primary-100 dark:hover:[#3c2632]"
|
||||
text="primary-300 hover:primary-500 dark:primary-300/50 dark:hover:primary-500"
|
||||
transition="all duration-250 ease-in-out"
|
||||
cursor-pointer items-center gap-1 px-2
|
||||
>
|
||||
@@ -160,15 +160,15 @@ onAfterSend(async () => {
|
||||
</label>
|
||||
<label
|
||||
:class="[
|
||||
tab === 'clothes' ? 'bg-pink-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'clothes' ? 'text-pink-500 dark:text-pink-500' : '',
|
||||
tab === 'clothes' ? 'bg-primary-100 dark:bg-[#3c2632]' : 'bg-white dark:bg-[#121212]',
|
||||
tab === 'clothes' ? 'text-primary-500 dark:text-primary-500' : '',
|
||||
]"
|
||||
flex="~ row"
|
||||
:checked="tab === 'clothes'"
|
||||
:aria-checked="tab === 'clothes'"
|
||||
border="solid r-2 t-2 b-2 pink-100 dark:[#3c2632]"
|
||||
bg="hover:pink-100 dark:hover:[#3c2632]"
|
||||
text="pink-300 hover:pink-500 dark:pink-300/50 dark:hover:pink-500"
|
||||
border="solid r-2 t-2 b-2 primary-100 dark:[#3c2632]"
|
||||
bg="hover:primary-100 dark:hover:[#3c2632]"
|
||||
text="primary-300 hover:primary-500 dark:primary-300/50 dark:hover:primary-500"
|
||||
transition="all duration-250 ease-in-out"
|
||||
cursor-pointer items-center gap-1 rounded-r-lg px-2
|
||||
>
|
||||
@@ -182,7 +182,7 @@ onAfterSend(async () => {
|
||||
<div h-full max-h="[85vh]" w-full px="12 <md:0" py="4">
|
||||
<div
|
||||
flex="~ col"
|
||||
border="solid 4 pink-100 dark:pink-400/20"
|
||||
border="solid 4 primary-100 dark:primary-400/20"
|
||||
h-full w-full overflow-scroll rounded-xl
|
||||
bg="white dark:[#0f060c]"
|
||||
>
|
||||
@@ -191,8 +191,8 @@ onAfterSend(async () => {
|
||||
<BasicTextarea
|
||||
v-model="messageInput"
|
||||
:placeholder="t('stage.message')"
|
||||
text="pink-300 hover:pink-500 dark:pink-300/50 dark:hover:pink-500 placeholder:pink-300 placeholder:hover:pink-500 placeholder:dark:pink-300/50 placeholder:dark:hover:pink-500"
|
||||
bg="pink-100 dark:pink-400/20"
|
||||
text="primary-300 hover:primary-500 dark:primary-300/50 dark:hover:primary-500 placeholder:primary-300 placeholder:hover:primary-500 placeholder:dark:primary-300/50 placeholder:dark:hover:primary-500"
|
||||
bg="primary-100 dark:primary-400/20"
|
||||
min-h="[100px]" w-full
|
||||
rounded-t-xl p-4 font-medium
|
||||
outline-none transition="all duration-250 ease-in-out placeholder:all placeholder:duration-250 placeholder:ease-in-out"
|
||||
|
||||
@@ -100,9 +100,9 @@ onMounted(() => {
|
||||
<BasicTextarea
|
||||
v-model="messageInput"
|
||||
:placeholder="t('stage.message')"
|
||||
border="solid 2 pink-100 dark:pink-400/20"
|
||||
text="pink-400 hover:pink-600 dark:[#905073] dark:hover:pink-600 placeholder:pink-400 placeholder:hover:pink-600 placeholder:dark:[#905073] placeholder:dark:hover:pink-600"
|
||||
bg="pink-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
border="solid 2 primary-100 dark:primary-400/20"
|
||||
text="primary-400 hover:primary-600 dark:[#905073] dark:hover:primary-600 placeholder:primary-400 placeholder:hover:primary-600 placeholder:dark:[#905073] placeholder:dark:hover:primary-600"
|
||||
bg="primary-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]"
|
||||
w-full resize-none overflow-y-scroll rounded-l-xl p-2 font-medium outline-none
|
||||
transition="all duration-250 ease-in-out placeholder:all placeholder:duration-250 placeholder:ease-in-out"
|
||||
@submit="handleSend"
|
||||
@@ -111,9 +111,9 @@ onMounted(() => {
|
||||
<DrawerRoot should-scale-background @update:open="handleSettingsOpen">
|
||||
<DrawerTrigger
|
||||
class="px-4 py-2.5"
|
||||
border="solid 2 pink-100 dark:pink-400/20"
|
||||
text="lg pink-400 hover:pink-600 dark:[#905073] dark:hover:pink-600 placeholder:pink-400 placeholder:hover:pink-600 placeholder:dark:[#905073] placeholder:dark:hover:pink-600"
|
||||
bg="pink-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]" rounded-r-xl
|
||||
border="solid 2 primary-100 dark:primary-400/20"
|
||||
text="lg primary-400 hover:primary-600 dark:[#905073] dark:hover:primary-600 placeholder:primary-400 placeholder:hover:primary-600 placeholder:dark:[#905073] placeholder:dark:hover:primary-600"
|
||||
bg="primary-50 dark:[#3c2632]" max-h="[10lh]" min-h="[1lh]" rounded-r-xl
|
||||
>
|
||||
<div i-solar:settings-bold-duotone />
|
||||
</DrawerTrigger>
|
||||
|
||||
@@ -11,9 +11,9 @@ defineProps<{
|
||||
<template>
|
||||
<RouterLink
|
||||
flex="~ row" bg="neutral-50 dark:neutral-800"
|
||||
border="neutral-100 dark:neutral-700 hover:pink-300 dark:hover:pink-300/40 solid 2"
|
||||
border="neutral-100 dark:neutral-700 hover:primary-300 dark:hover:primary-300/40 solid 2"
|
||||
drop-shadow="none hover:[0px_4px_4px_rgba(220,220,220,0.4)] active:[0px_0px_0px_rgba(220,220,220,0.25)] dark:hover:none"
|
||||
class="after:mask-[linear-gradient(165deg,white_30%,transparent_50%)] after:bg-dotted-[neutral-200] after:hover:bg-dotted-[pink-300/50] dark:after:bg-dotted-[neutral-700/80] dark:after:hover:bg-dotted-[pink-200/20] after:absolute after:left-0 after:top-0 after:z--1 after:h-full after:w-full after:bg-[size:10px_10px] after:content-empty [&_.settings-section-icon]:hover:scale-120 [&_.settings-section-description]:hover:text-pink-400/80 [&_.settings-section-icon]:hover:text-pink-200 [&_.settings-section-title]:hover:text-pink-500 dark:[&_.settings-section-icon]:hover:text-pink-200/40 dark:[&_.settings-section-title]:hover:text-pink-400"
|
||||
class="after:mask-[linear-gradient(165deg,white_30%,transparent_50%)] after:bg-dotted-[neutral-200] after:hover:bg-dotted-[primary-300/50] dark:after:bg-dotted-[neutral-700/80] [&_.settings-section-description]:hover:text-primary-400/80 [&_.settings-section-icon]:hover:text-primary-200 [&_.settings-section-title]:hover:text-primary-500 dark:after:hover:bg-dotted-[primary-200/20] dark:[&_.settings-section-icon]:hover:text-primary-200/40 dark:[&_.settings-section-title]:hover:text-primary-400 after:absolute after:left-0 after:top-0 after:z--1 after:h-full after:w-full after:bg-[size:10px_10px] after:content-empty [&_.settings-section-icon]:hover:scale-120"
|
||||
transition="all ease-in-out duration-200" relative w-full items-center overflow-hidden rounded-lg p-5 text-left
|
||||
:to="to"
|
||||
>
|
||||
|
||||
@@ -58,11 +58,11 @@ onTokenLiteral(async () => {
|
||||
</div>
|
||||
<div v-if="message.role === 'assistant'" flex mr="12">
|
||||
<div
|
||||
flex="~ col" border="4 solid pink-200/50 dark:pink-500/50" shadow="md pink-200/50 dark:none" min-w-20
|
||||
rounded-lg px-2 py-1 h="unset <sm:fit" bg="<md:pink-500/25"
|
||||
flex="~ col" border="4 solid primary-200/50 dark:primary-500/50" shadow="md primary-200/50 dark:none" min-w-20
|
||||
rounded-lg px-2 py-1 h="unset <sm:fit" bg="<md:primary-500/25"
|
||||
>
|
||||
<div>
|
||||
<span text-xs text="pink-400/90 dark:pink-600/90" font-semibold class="inline <sm:hidden">{{
|
||||
<span text-xs text="primary-400/90 dark:primary-600/90" font-semibold class="inline <sm:hidden">{{
|
||||
$t('stage.chat.message.character-name.airi') }}</span>
|
||||
</div>
|
||||
<div v-if="sending" i-eos-icons:three-dots-loading />
|
||||
|
||||
@@ -31,8 +31,15 @@ watch(() => settings.loadingLive2dModel, (value) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (settings.live2dLoadSource !== 'file') {
|
||||
return
|
||||
}
|
||||
|
||||
settings.availableLive2dMotions.forEach((motion) => {
|
||||
if (!settings.live2dMotionMap[motion.fileName]) {
|
||||
if (motion.motionName in Emotion) {
|
||||
settings.live2dMotionMap[motion.fileName] = motion.motionName
|
||||
}
|
||||
else {
|
||||
settings.live2dMotionMap[motion.fileName] = EmotionNeutralMotionName
|
||||
}
|
||||
})
|
||||
@@ -88,161 +95,163 @@ const exportObjectUrl = useObjectUrl(settings.live2dModelFile)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Collapsable w-full>
|
||||
<template #trigger="slotProps">
|
||||
<button
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
|
||||
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
|
||||
@click="slotProps.setVisible(!slotProps.visible)"
|
||||
>
|
||||
<div flex="~ row 1" items-center gap-1.5>
|
||||
<div
|
||||
i-solar:magic-stick-3-bold-duotone class="provider-icon size-6"
|
||||
transition="filter duration-250 ease-in-out"
|
||||
/>
|
||||
<div>
|
||||
{{ t('settings.live2d.change-model.title') }}
|
||||
</div>
|
||||
</div>
|
||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||
<div i-solar:alt-arrow-down-bold-duotone />
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
<div p-4>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ t('settings.live2d.change-model.from-url') }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
v-model="modelUrl"
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
type="text"
|
||||
rounded
|
||||
border="zinc-300 dark:zinc-800 solid 1 focus:zinc-400 dark:focus:zinc-600"
|
||||
transition="border duration-250 ease-in-out"
|
||||
px-2 py-1 text-sm outline-none
|
||||
:placeholder="t('settings.live2d.change-model.from-url-placeholder')"
|
||||
>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
ml-2 rounded px-2 py-1 text-sm outline-none
|
||||
@click="settings.live2dModelUrl = modelUrl"
|
||||
>
|
||||
{{ t('settings.live2d.change-model.from-url-confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ t('settings.live2d.change-model.from-file') }}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
px-2 py-1 text-sm outline-none
|
||||
@click="modelFile.open()"
|
||||
>
|
||||
{{ t('settings.live2d.change-model.from-file-select') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Collapsable>
|
||||
<Collapsable mt-4 w-full>
|
||||
<template #trigger="slotProps">
|
||||
<button
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
|
||||
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
|
||||
@click="slotProps.setVisible(!slotProps.visible)"
|
||||
>
|
||||
<div flex="~ row 1" items-center gap-1.5>
|
||||
<div
|
||||
i-solar:face-scan-circle-bold-duotone class="provider-icon size-6"
|
||||
transition="filter duration-250 ease-in-out"
|
||||
/>
|
||||
<div>
|
||||
Edit motion map
|
||||
</div>
|
||||
</div>
|
||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||
<div i-solar:alt-arrow-down-bold-duotone />
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
<div p-4>
|
||||
<div v-if="settings.live2dLoadSource === 'file'" class="space-y-4">
|
||||
<div v-for="motion in settings.availableLive2dMotions" :key="motion.fileName" class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ motion.fileName }}
|
||||
</div>
|
||||
|
||||
<div flex gap-2>
|
||||
<select v-model="settings.live2dMotionMap[motion.fileName]">
|
||||
<option v-for="emotion in Object.keys(Emotion)" :key="emotion">
|
||||
{{ emotion }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
px-2 py-1 text-sm outline-none
|
||||
@click="settings.live2dCurrentMotion = { group: motion.motionName, index: motion.motionIndex }"
|
||||
>
|
||||
Play
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Collapsable w-full :default="true">
|
||||
<template #trigger="slotProps">
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
w-full rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
@click="saveMotionMap"
|
||||
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
|
||||
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
|
||||
@click="slotProps.setVisible(!slotProps.visible)"
|
||||
>
|
||||
Save and patch
|
||||
<div flex="~ row 1" items-center gap-1.5>
|
||||
<div
|
||||
i-solar:magic-stick-3-bold-duotone class="provider-icon size-6"
|
||||
transition="filter duration-250 ease-in-out"
|
||||
/>
|
||||
<div>
|
||||
{{ t('settings.live2d.change-model.title') }}
|
||||
</div>
|
||||
</div>
|
||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||
<div i-solar:alt-arrow-down-bold-duotone />
|
||||
</div>
|
||||
</button>
|
||||
<a
|
||||
mt-2 block :href="exportObjectUrl"
|
||||
:download="`${settings.live2dModelFile?.name}-motion-edited.zip`"
|
||||
</template>
|
||||
<div p-4>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ t('settings.live2d.change-model.from-url') }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
v-model="modelUrl"
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
type="text"
|
||||
rounded
|
||||
border="zinc-300 dark:zinc-800 solid 1 focus:zinc-400 dark:focus:zinc-600"
|
||||
transition="border duration-250 ease-in-out"
|
||||
px-2 py-1 text-sm outline-none
|
||||
:placeholder="t('settings.live2d.change-model.from-url-placeholder')"
|
||||
>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
ml-2 rounded px-2 py-1 text-sm outline-none
|
||||
@click="settings.live2dModelUrl = modelUrl"
|
||||
>
|
||||
{{ t('settings.live2d.change-model.from-url-confirm') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ t('settings.live2d.change-model.from-file') }}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
px-2 py-1 text-sm outline-none
|
||||
@click="modelFile.open()"
|
||||
>
|
||||
{{ t('settings.live2d.change-model.from-file-select') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Collapsable>
|
||||
<Collapsable mt-4 w-full :default="true">
|
||||
<template #trigger="slotProps">
|
||||
<button
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
|
||||
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
|
||||
@click="slotProps.setVisible(!slotProps.visible)"
|
||||
>
|
||||
<div flex="~ row 1" items-center gap-1.5>
|
||||
<div
|
||||
i-solar:face-scan-circle-bold-duotone class="provider-icon size-6"
|
||||
transition="filter duration-250 ease-in-out"
|
||||
/>
|
||||
<div>
|
||||
Edit motion map
|
||||
</div>
|
||||
</div>
|
||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||
<div i-solar:alt-arrow-down-bold-duotone />
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
<div p-4>
|
||||
<div v-if="settings.live2dLoadSource === 'file'" class="space-y-4">
|
||||
<div v-for="motion in settings.availableLive2dMotions" :key="motion.fileName" class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ motion.fileName }}
|
||||
</div>
|
||||
|
||||
<div flex gap-2>
|
||||
<select v-model="settings.live2dMotionMap[motion.fileName]">
|
||||
<option v-for="emotion in Object.keys(Emotion)" :key="emotion">
|
||||
{{ emotion }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
px-2 py-1 text-sm outline-none
|
||||
@click="settings.live2dCurrentMotion = { group: motion.motionName, index: motion.motionIndex }"
|
||||
>
|
||||
Play
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
w-full rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
@click="saveMotionMap"
|
||||
>
|
||||
Export
|
||||
Save and patch
|
||||
</button>
|
||||
</a>
|
||||
<a
|
||||
mt-2 block :href="exportObjectUrl"
|
||||
:download="`${settings.live2dModelFile?.name}-motion-edited.zip`"
|
||||
>
|
||||
<button
|
||||
:disabled="settings.loadingLive2dModel"
|
||||
w-full rounded
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
Export
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div v-else>
|
||||
Not available for URL model
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
Not available for URL model
|
||||
</div>
|
||||
</div>
|
||||
</Collapsable>
|
||||
</Collapsable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -40,14 +40,14 @@ onTokenLiteral(async () => {
|
||||
<div v-if="message.role === 'assistant'" flex mr="12">
|
||||
<div
|
||||
flex="~ col"
|
||||
border="4 solid pink-200/50 dark:pink-500/50"
|
||||
shadow="md pink-200/50 dark:none"
|
||||
border="4 solid primary-200/50 dark:primary-500/50"
|
||||
shadow="md primary-200/50 dark:none"
|
||||
min-w-20 rounded-lg px-2 py-1
|
||||
h="unset <sm:fit"
|
||||
bg="<md:pink-500/25"
|
||||
bg="<md:primary-500/25"
|
||||
>
|
||||
<div>
|
||||
<span text-xs text="pink-400/90 dark:pink-600/90" font-semibold class="inline <sm:hidden">{{ $t('stage.chat.message.character-name.airi') }}</span>
|
||||
<span text-xs text="primary-400/90 dark:primary-600/90" font-semibold class="inline <sm:hidden">{{ $t('stage.chat.message.character-name.airi') }}</span>
|
||||
</div>
|
||||
<div v-if="message.content" class="markdown-content" text="base <sm:xs" v-html="process(message.content as string)" />
|
||||
<div v-else i-eos-icons:three-dots-loading />
|
||||
|
||||
@@ -20,7 +20,7 @@ function handleSettingsOpen(open: boolean) {
|
||||
|
||||
<template>
|
||||
<Cross>
|
||||
<AnimatedBackground :fill-color="dark ? '#563544' : '#f8e8f2'">
|
||||
<AnimatedBackground :fill-color="dark ? 'oklch(95% 0.20 var(--theme-colors-hue))' : 'oklch(99% 0.10 var(--theme-colors-hue))'">
|
||||
<div relative flex="~ col" z-2 h-100vh w-100vw of-hidden>
|
||||
<!-- header -->
|
||||
<div>
|
||||
|
||||
@@ -9,12 +9,12 @@ import IconItem from '../../components/Menu/IconItem.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
const settings = storeToRefs(useSettings())
|
||||
const { language, disableTransitions } = storeToRefs(useSettings())
|
||||
const dark = useDark()
|
||||
|
||||
function handleLanguageChange(event: Event) {
|
||||
const target = event.target as HTMLSelectElement
|
||||
settings.language.value = target.value
|
||||
language.value = target.value
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -104,6 +104,41 @@ function handleLanguageChange(event: Event) {
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<!-- Developer Settings -->
|
||||
<label
|
||||
bg="neutral-100 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
w-full flex cursor-pointer rounded-lg px-4 py-3
|
||||
>
|
||||
<input
|
||||
v-model="disableTransitions"
|
||||
text="neutral-800 dark:neutral-100"
|
||||
:checked="disableTransitions"
|
||||
:aria-checked="disableTransitions"
|
||||
type="checkbox"
|
||||
hidden appearance-none outline-none
|
||||
>
|
||||
<div flex="~ row" w-full items-center gap-1.5>
|
||||
<div text="sm" w-full flex-1>
|
||||
<span>Disable Transitions (for debugging)</span>
|
||||
</div>
|
||||
<div select-none>
|
||||
<Transition name="slide-away" mode="out-in">
|
||||
<div
|
||||
v-if="disableTransitions"
|
||||
i-solar:people-nearby-bold-duotone
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
i-solar:running-2-line-duotone
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div fixed bottom-0 right-0 text="neutral-100/50 dark:neutral-500/20">
|
||||
<div text="40" i-lucide:cog translate-x-10 translate-y-10 />
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { WidgetStage } from '@proj-airi/stage-ui/components'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import Live2DSettings from '../../../components/Widgets/Live2DSettings.vue'
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
@@ -18,6 +21,11 @@ const router = useRouter()
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
<div flex>
|
||||
<WidgetStage w="50%" h="80vh" />
|
||||
<Live2DSettings w="50%" h="80vh" />
|
||||
</div>
|
||||
|
||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
||||
<div text="40" i-lucide:person-standing translate-x-10 translate-y-10 />
|
||||
</div>
|
||||
|
||||
@@ -111,9 +111,9 @@ const modulesList = computed<Module[]>(() => [
|
||||
<div
|
||||
v-for="module in modulesList" :key="module.id"
|
||||
bg="neutral-200/50 dark:neutral-700"
|
||||
border="neutral-100 dark:neutral-700 hover:pink-300 dark:hover:pink-300/40 solid 2"
|
||||
border="neutral-100 dark:neutral-700 hover:primary-300 dark:hover:primary-300/40 solid 2"
|
||||
drop-shadow="none hover:[0px_4px_4px_rgba(220,220,220,0.4)] active:[0px_0px_0px_rgba(220,220,220,0.25)] dark:hover:none"
|
||||
class="[&_.settings-section-icon]:hover:scale-120 [&_.settings-section-description]:hover:text-pink-400/80 [&_.settings-section-icon]:hover:text-pink-200 [&_.settings-section-icon]:hover:grayscale-0 dark:[&_.settings-section-icon]:hover:text-pink-200/40 dark:[&_.settings-section-title]:hover:text-pink-400"
|
||||
class="[&_.settings-section-description]:hover:text-primary-400/80 [&_.settings-section-icon]:hover:text-primary-200 dark:[&_.settings-section-icon]:hover:text-primary-200/40 dark:[&_.settings-section-title]:hover:text-primary-400 [&_.settings-section-icon]:hover:scale-120 [&_.settings-section-icon]:hover:grayscale-0"
|
||||
w-full of-hidden rounded-xl
|
||||
flex="~ col 1"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { Collapsable } from '@proj-airi/stage-ui/components'
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const settings = useSettings()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -18,11 +21,98 @@ const router = useRouter()
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
<Collapsable mt-4 w-full :default="true">
|
||||
<template #trigger="slotProps">
|
||||
<button
|
||||
bg="zinc-100 dark:zinc-800"
|
||||
hover="bg-zinc-200 dark:bg-zinc-700"
|
||||
transition="all ease-in-out duration-250"
|
||||
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
|
||||
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
|
||||
@click="slotProps.setVisible(!slotProps.visible)"
|
||||
>
|
||||
<div flex="~ row 1" items-center gap-1.5>
|
||||
<div
|
||||
i-solar:pallete-2-bold-duotone class="provider-icon size-6"
|
||||
transition="filter duration-250 ease-in-out"
|
||||
/>
|
||||
<div>
|
||||
Colors
|
||||
</div>
|
||||
</div>
|
||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||
<div i-solar:alt-arrow-down-bold-duotone />
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
<div p-4>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
Primary color
|
||||
</div>
|
||||
|
||||
<input v-model="settings.themeColorsHue" type="range" min="0" max="360" step="1">
|
||||
</div>
|
||||
<div mt-4 h-10 w-full flex overflow-hidden rounded-lg>
|
||||
<div bg="primary-50" class="primary-color-bar">
|
||||
50
|
||||
</div>
|
||||
<div bg="primary-100" class="primary-color-bar">
|
||||
100
|
||||
</div>
|
||||
<div bg="primary-200" class="primary-color-bar">
|
||||
200
|
||||
</div>
|
||||
<div bg="primary-300" class="primary-color-bar">
|
||||
300
|
||||
</div>
|
||||
<div bg="primary-400" class="primary-color-bar">
|
||||
400
|
||||
</div>
|
||||
<div bg="primary-500" class="primary-color-bar">
|
||||
500
|
||||
</div>
|
||||
<div bg="primary-600" class="primary-color-bar">
|
||||
600
|
||||
</div>
|
||||
<div bg="primary-700" class="primary-color-bar">
|
||||
700
|
||||
</div>
|
||||
<div bg="primary-800" class="primary-color-bar" text-white>
|
||||
800
|
||||
</div>
|
||||
<div bg="primary-900" class="primary-color-bar" text-white>
|
||||
900
|
||||
</div>
|
||||
<div bg="primary-950" class="primary-color-bar" text-white>
|
||||
950
|
||||
</div>
|
||||
<div bg="primary-960" class="primary-color-bar" text-white>
|
||||
960
|
||||
</div>
|
||||
<div bg="primary-970" class="primary-color-bar" text-white>
|
||||
970
|
||||
</div>
|
||||
<div bg="primary-980" class="primary-color-bar" text-white>
|
||||
980
|
||||
</div>
|
||||
<div bg="primary-990" class="primary-color-bar" text-white>
|
||||
990
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Collapsable>
|
||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
||||
<div text="40" i-lucide:paintbrush translate-x-10 translate-y-10 />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.primary-color-bar {
|
||||
@apply w-full h-full flex-1 flex items-center justify-center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
stageTransition:
|
||||
|
||||
@@ -10,4 +10,5 @@
|
||||
--airi-theme-primary-800: #a70a3e;
|
||||
--airi-theme-primary-900: #8e0d3b;
|
||||
--airi-theme-primary-950: #50011b;
|
||||
--theme-colors-hue: 354.31;
|
||||
}
|
||||
|
||||
@@ -69,4 +69,26 @@ export default defineConfig({
|
||||
}
|
||||
}],
|
||||
],
|
||||
theme: {
|
||||
colors: {
|
||||
primary: {
|
||||
DEFAULT: 'oklch(62% 0.20 var(--theme-colors-hue))',
|
||||
50: 'color-mix(in srgb, oklch(95% 0.10 var(--theme-colors-hue)) 30%, oklch(100% 0 360))',
|
||||
100: 'color-mix(in srgb, oklch(95% 0.10 var(--theme-colors-hue)) 80%, oklch(100% 0 360))',
|
||||
200: 'oklch(90% 0.12 var(--theme-colors-hue))',
|
||||
300: 'oklch(85% 0.20 var(--theme-colors-hue))',
|
||||
400: 'oklch(74% 0.20 var(--theme-colors-hue))',
|
||||
500: 'oklch(62% 0.20 var(--theme-colors-hue))',
|
||||
600: 'oklch(54% 0.23 var(--theme-colors-hue))',
|
||||
700: 'oklch(49% 0.21 var(--theme-colors-hue))',
|
||||
800: 'oklch(42% 0.17 var(--theme-colors-hue))',
|
||||
900: 'oklch(37% 0.14 var(--theme-colors-hue))',
|
||||
950: 'oklch(29% 0.09 var(--theme-colors-hue))',
|
||||
960: 'oklch(23% 0.09 var(--theme-colors-hue))',
|
||||
970: 'oklch(17% 0.09 var(--theme-colors-hue))',
|
||||
980: 'oklch(11% 0.09 var(--theme-colors-hue))',
|
||||
990: 'oklch(6% 0.09 var(--theme-colors-hue))',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -252,11 +252,11 @@ onMounted(async () => {
|
||||
bottom="20%"
|
||||
z="20"
|
||||
rounded-2xl
|
||||
text="pink-600"
|
||||
text="primary-600"
|
||||
px-2 py-2
|
||||
transform="translate-x--1/2"
|
||||
>
|
||||
<div bg="pink-50" rounded-xl px-10 py-6>
|
||||
<div bg="primary-50" rounded-xl px-10 py-6>
|
||||
<div class="markdown-content" v-html="process(streamingMessage.content as string)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,6 +33,10 @@ export const useSettings = defineStore('settings', () => {
|
||||
const availableLive2dMotions = ref<{ motionName: string, motionIndex: number, fileName: string }[]>([])
|
||||
const live2dMotionMap = useLocalStorage<Record<string, string>>('settings/live2d/motion-map', {})
|
||||
|
||||
const disableTransitions = useLocalStorage('settings/disable-transitions', false)
|
||||
|
||||
const themeColorsHue = useLocalStorage('settings/theme/colors/hue', 354.31)
|
||||
|
||||
watch(isAudioInputOn, (value) => {
|
||||
if (value === 'false') {
|
||||
selectedAudioDevice.value = undefined
|
||||
@@ -67,8 +71,10 @@ export const useSettings = defineStore('settings', () => {
|
||||
availableLive2dMotions,
|
||||
live2dMotionMap,
|
||||
loadingLive2dModel,
|
||||
disableTransitions,
|
||||
language,
|
||||
stageView,
|
||||
themeColorsHue,
|
||||
isAudioInputOn,
|
||||
selectedAudioDevice,
|
||||
selectedAudioDeviceId,
|
||||
|
||||
@@ -16,6 +16,7 @@ const props = defineProps<{
|
||||
tertiaryColor?: string
|
||||
colors?: string[]
|
||||
zIndex?: number
|
||||
disableTransitions?: boolean
|
||||
}>()
|
||||
|
||||
interface StageTransitionCommonParams {
|
||||
@@ -268,6 +269,11 @@ router.beforeEach((to, _from, next) => {
|
||||
stageTransition.zIndex = props.zIndex
|
||||
}
|
||||
|
||||
if (props.disableTransitions) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
triggerTransition(stageTransition, next)
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user