fix(stage-web|stage-tamagotchi): format
This commit is contained in:
@@ -4,7 +4,9 @@ import { useSettings } from '@proj-airi/stage-ui/stores'
|
|||||||
import { useDark } from '@vueuse/core'
|
import { useDark } from '@vueuse/core'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { language, disableTransitions } = storeToRefs(useSettings())
|
const { language, disableTransitions } = storeToRefs(useSettings())
|
||||||
const dark = useDark()
|
const dark = useDark()
|
||||||
@@ -12,19 +14,12 @@ const dark = useDark()
|
|||||||
function handleLanguageChange(event: Event) {
|
function handleLanguageChange(event: Event) {
|
||||||
const target = event.target as HTMLSelectElement
|
const target = event.target as HTMLSelectElement
|
||||||
language.value = target.value
|
language.value = target.value
|
||||||
// Send IPC message to main process for locale change
|
|
||||||
window.electron?.ipcRenderer.send('locale-changed', target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle window close
|
|
||||||
function handleClose() {
|
|
||||||
window.electron?.ipcRenderer.send('close-settings')
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div flex="~ row" items-center gap-2>
|
<div flex="~ row" items-center gap-2>
|
||||||
<button @click="handleClose">
|
<button @click="router.back()">
|
||||||
<div i-solar:alt-arrow-left-line-duotone text-2xl />
|
<div i-solar:alt-arrow-left-line-duotone text-2xl />
|
||||||
</button>
|
</button>
|
||||||
<h1 text-3xl>
|
<h1 text-3xl>
|
||||||
@@ -34,7 +29,7 @@ function handleClose() {
|
|||||||
<div flex="~ col gap-4">
|
<div flex="~ col gap-4">
|
||||||
<div flex="~ col gap-4">
|
<div flex="~ col gap-4">
|
||||||
<IconItem title="Modules" description="Thinking, vision, speech synthesis, gaming, etc." icon="i-lucide:blocks" to="/settings/modules" />
|
<IconItem title="Modules" description="Thinking, vision, speech synthesis, gaming, etc." icon="i-lucide:blocks" to="/settings/modules" />
|
||||||
<!-- <IconItem title="Models" description="Live2D, VRM, etc." icon="i-lucide:person-standing" to="/settings/models" /> -->
|
<IconItem title="Models" description="Live2D, VRM, etc." icon="i-lucide:person-standing" to="/settings/models" />
|
||||||
<IconItem title="Providers" description="LLMs, speech providers, etc." icon="i-lucide:brain" to="/settings/providers" />
|
<IconItem title="Providers" description="LLMs, speech providers, etc." icon="i-lucide:brain" to="/settings/providers" />
|
||||||
<IconItem title="Themes" description="Customize your stage!" icon="i-lucide:paintbrush" to="/settings/themes" />
|
<IconItem title="Themes" description="Customize your stage!" icon="i-lucide:paintbrush" to="/settings/themes" />
|
||||||
</div>
|
</div>
|
||||||
@@ -145,8 +140,14 @@ function handleClose() {
|
|||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0>
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:cog translate-x-10 translate-y-10 />
|
<div v-motion text="40" i-lucide:cog />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div flex="~ row" items-center gap-2>
|
||||||
|
<button @click="router.back()">
|
||||||
|
<div i-solar:alt-arrow-left-line-duotone text-2xl />
|
||||||
|
</button>
|
||||||
|
<h1 relative>
|
||||||
|
<div absolute left-0 top-0 translate-y="[-80%]">
|
||||||
|
<span text="neutral-300 dark:neutral-500">Settings</span>
|
||||||
|
</div>
|
||||||
|
<div text-3xl font-semibold>
|
||||||
|
Models
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div flex>
|
||||||
|
<WidgetStage w="50%" h="80vh" />
|
||||||
|
<Live2DSettings w="50%" h="80vh" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
|
<div text="40" i-lucide:person-standing />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
@@ -205,7 +205,13 @@ function updateCustomModelName(value: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 class="text-neutral-100/80 dark:text-neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:ghost translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:ghost />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
|
|||||||
@@ -120,7 +120,13 @@ const modulesList = computed<Module[]>(() => [
|
|||||||
:configured="module.configured"
|
:configured="module.configured"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:blocks translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:blocks />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ function updateSSMLExample() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 class="text-neutral-100/80 dark:text-neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:volume-2 translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:volume-2 />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ function handleResetVoiceSettings() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" :class="providerMetadata?.icon" translate-x-10 translate-y-10 />
|
<div text="40" :class="providerMetadata?.icon" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -32,11 +32,17 @@ const { allProvidersMetadata } = storeToRefs(providersStore)
|
|||||||
:icon="provider.icon"
|
:icon="provider.icon"
|
||||||
:icon-color="provider.iconColor"
|
:icon-color="provider.iconColor"
|
||||||
:icon-image="provider.iconImage"
|
:icon-image="provider.iconImage"
|
||||||
:to="`/settings/providers/${provider.id.replace('-ai', '')}`"
|
:to="`/settings/providers/${provider.id}`"
|
||||||
:configured="provider.configured"
|
:configured="provider.configured"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:brain translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:brain />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ watch([apiKey, baseUrl], () => {
|
|||||||
</Collapsable>
|
</Collapsable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lobe-icons:openai translate-x-10 translate-y-10 />
|
<div text="40" i-lobe-icons:openai />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ watch([apiKey, baseUrl], () => {
|
|||||||
</Collapsable>
|
</Collapsable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" :class="providerMetadata?.icon" translate-x-10 translate-y-10 />
|
<div text="40" :class="providerMetadata?.icon" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,15 +1,137 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Collapsable } from '@proj-airi/stage-ui/components'
|
import { Collapsable } from '@proj-airi/stage-ui/components'
|
||||||
import { DEFAULT_THEME_COLORS_HUE, useSettings } from '@proj-airi/stage-ui/stores'
|
import { DEFAULT_THEME_COLORS_HUE, useSettings } from '@proj-airi/stage-ui/stores'
|
||||||
|
import { converter } from 'culori'
|
||||||
|
import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const settings = useSettings()
|
const settings = useSettings()
|
||||||
|
|
||||||
|
interface ColorPreset {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
colors: Array<{
|
||||||
|
hex: string
|
||||||
|
name: string
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorPresets: ColorPreset[] = [
|
||||||
|
{
|
||||||
|
name: 'Morandi Colors',
|
||||||
|
description: 'Soft, muted tones inspired by Giorgio Morandi\'s paintings',
|
||||||
|
colors: [
|
||||||
|
{ hex: '#A5978B', name: 'Taupe' },
|
||||||
|
{ hex: '#D8CAAF', name: 'Beige' },
|
||||||
|
{ hex: '#B8B4A7', name: 'Ash Grey' },
|
||||||
|
{ hex: '#C4BCB1', name: 'Light Taupe' },
|
||||||
|
{ hex: '#E5DED8', name: 'Ivory' },
|
||||||
|
{ hex: '#9A8F7D', name: 'Olive Grey' },
|
||||||
|
{ hex: '#BEB5A7', name: 'Sand' },
|
||||||
|
{ hex: '#C9C0B6', name: 'Warm Grey' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Monet Colors',
|
||||||
|
description: 'Impressionist palette inspired by Claude Monet\'s works',
|
||||||
|
colors: [
|
||||||
|
{ hex: '#7A9EAF', name: 'Sky Blue' },
|
||||||
|
{ hex: '#B8C7CC', name: 'Mist' },
|
||||||
|
{ hex: '#D4B79C', name: 'Sand' },
|
||||||
|
{ hex: '#8B9D77', name: 'Moss Green' },
|
||||||
|
{ hex: '#C7D5CB', name: 'Water Lily' },
|
||||||
|
{ hex: '#E6D0B1', name: 'Wheat' },
|
||||||
|
{ hex: '#94A7B1', name: 'Slate Blue' },
|
||||||
|
{ hex: '#B4C8C3', name: 'Sage' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Japanese Colors',
|
||||||
|
description: 'Traditional Japanese color palette',
|
||||||
|
colors: [
|
||||||
|
{ hex: '#D9B48F', name: 'Tan' },
|
||||||
|
{ hex: '#B5917A', name: 'Warm Taupe' },
|
||||||
|
{ hex: '#8C7A6B', name: 'Umber' },
|
||||||
|
{ hex: '#A17F5F', name: 'Coffee' },
|
||||||
|
{ hex: '#B98C46', name: 'Bronze' },
|
||||||
|
{ hex: '#C7A252', name: 'Gold' },
|
||||||
|
{ hex: '#DAB300', name: 'Mustard' },
|
||||||
|
{ hex: '#D19826', name: 'Amber' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Nordic Colors',
|
||||||
|
description: 'Scandinavian minimalist color scheme',
|
||||||
|
colors: [
|
||||||
|
{ hex: '#9BA7B0', name: 'Nordic Blue' },
|
||||||
|
{ hex: '#C1CBD4', name: 'Ice' },
|
||||||
|
{ hex: '#A5ADB6', name: 'Fjord' },
|
||||||
|
{ hex: '#8B959E', name: 'Steel' },
|
||||||
|
{ hex: '#D4DCE4', name: 'Glacier' },
|
||||||
|
{ hex: '#7F8A94', name: 'Slate' },
|
||||||
|
{ hex: '#B3BCC6', name: 'Cloud' },
|
||||||
|
{ hex: '#98A4AE', name: 'Stone' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Chinese Traditional Colors',
|
||||||
|
description: 'Traditional Chinese colors, derived from ancient textiles, porcelain and paintings',
|
||||||
|
colors: [
|
||||||
|
{ hex: '#E4C6D0', name: '霞光红 (Rosy Dawn)' },
|
||||||
|
{ hex: '#A61B29', name: '枣红 (Chinese Red)' },
|
||||||
|
{ hex: '#5D513C', name: '黄栌 (Smoky Brown)' },
|
||||||
|
{ hex: '#789262', name: '竹青 (Bamboo Green)' },
|
||||||
|
{ hex: '#1C0D1A', name: '乌梅紫 (Dark Purple)' },
|
||||||
|
{ hex: '#F7C242', name: '缃色 (Golden Yellow)' },
|
||||||
|
{ hex: '#62A9DD', name: '青冥 (Azure Blue)' },
|
||||||
|
{ hex: '#8C4B3C', name: '赭石 (Ochre)' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
function resetToDefault() {
|
function resetToDefault() {
|
||||||
settings.themeColorsHue = DEFAULT_THEME_COLORS_HUE
|
settings.themeColorsHue = DEFAULT_THEME_COLORS_HUE
|
||||||
settings.themeColorsHueDynamic = false
|
settings.themeColorsHueDynamic = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyPrimaryColorFromHex(color: string) {
|
||||||
|
// Convert hex color to OKLCH using culori's converter
|
||||||
|
const oklch = converter('oklch')(color)
|
||||||
|
|
||||||
|
if (!oklch)
|
||||||
|
return
|
||||||
|
|
||||||
|
// Extract hue from OKLCH color
|
||||||
|
const { h } = oklch
|
||||||
|
|
||||||
|
if (!h)
|
||||||
|
return
|
||||||
|
|
||||||
|
// Update theme settings
|
||||||
|
settings.themeColorsHue = h
|
||||||
|
settings.themeColorsHueDynamic = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a color is currently selected based on its hue value
|
||||||
|
* @param hexColor Hex color code to check
|
||||||
|
* @returns True if the color's hue matches the current theme hue
|
||||||
|
*/
|
||||||
|
function isColorSelected(hexColor: string): boolean {
|
||||||
|
// If dynamic coloring is enabled, no preset color is manually selected
|
||||||
|
if (settings.themeColorsHueDynamic)
|
||||||
|
return false
|
||||||
|
|
||||||
|
// Convert hex color to OKLCH
|
||||||
|
const oklch = converter('oklch')(hexColor)
|
||||||
|
if (!oklch || !oklch.h)
|
||||||
|
return false
|
||||||
|
|
||||||
|
// Compare hue values with a small tolerance for floating point comparison
|
||||||
|
const hueDifference = Math.abs(oklch.h - settings.themeColorsHue)
|
||||||
|
return hueDifference < 0.01 || hueDifference > 359.99
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -26,6 +148,8 @@ function resetToDefault() {
|
|||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div flex-col>
|
||||||
<Collapsable mt-4 w-full :default="true">
|
<Collapsable mt-4 w-full :default="true">
|
||||||
<template #trigger="slotProps">
|
<template #trigger="slotProps">
|
||||||
<button
|
<button
|
||||||
@@ -42,7 +166,7 @@ function resetToDefault() {
|
|||||||
transition="filter duration-250 ease-in-out"
|
transition="filter duration-250 ease-in-out"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
Colors
|
Custom Colors
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
|
||||||
@@ -51,23 +175,23 @@ function resetToDefault() {
|
|||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<div p-4>
|
<div p-4>
|
||||||
<div class="flex items-center gap-8">
|
<div class="mb-2 text-sm font-medium">
|
||||||
<div class="flex items-center gap-1 text-sm font-medium">
|
|
||||||
Primary color
|
Primary color
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div flex="~ col gap-4">
|
||||||
<input
|
<input
|
||||||
v-model="settings.themeColorsHue"
|
v-model="settings.themeColorsHue"
|
||||||
type="range"
|
type="range"
|
||||||
min="0"
|
min="0"
|
||||||
max="360"
|
max="360"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
class="theme-hue-slider"
|
class="theme-hue-slider h-10 w-full"
|
||||||
:disabled="settings.themeColorsHueDynamic"
|
:disabled="settings.themeColorsHueDynamic"
|
||||||
:class="{ 'opacity-25 cursor-not-allowed': settings.themeColorsHueDynamic }"
|
:class="{ 'opacity-25 cursor-not-allowed': settings.themeColorsHueDynamic }"
|
||||||
>
|
>
|
||||||
</div>
|
|
||||||
<div mt-4 h-10 w-full flex overflow-hidden rounded-lg>
|
<div h-10 w-full flex overflow-hidden rounded-lg>
|
||||||
<div bg="primary-50" class="primary-color-bar" text-black>
|
<div bg="primary-50" class="primary-color-bar" text-black>
|
||||||
50
|
50
|
||||||
</div>
|
</div>
|
||||||
@@ -103,7 +227,7 @@ function resetToDefault() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div mt-4 h-10 w-full flex overflow-hidden rounded-lg class="transparency-grid">
|
<div h-10 w-full flex overflow-hidden rounded-lg class="transparency-grid">
|
||||||
<div bg="primary-500/5" class="primary-color-bar" text-black>
|
<div bg="primary-500/5" class="primary-color-bar" text-black>
|
||||||
500/5
|
500/5
|
||||||
</div>
|
</div>
|
||||||
@@ -138,6 +262,8 @@ function resetToDefault() {
|
|||||||
500
|
500
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div mt-4 class="flex items-center justify-end gap-4">
|
<div mt-4 class="flex items-center justify-end gap-4">
|
||||||
<label class="relative inline-flex cursor-pointer items-center">
|
<label class="relative inline-flex cursor-pointer items-center">
|
||||||
<input
|
<input
|
||||||
@@ -160,18 +286,90 @@ function resetToDefault() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Collapsable>
|
</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 />
|
<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:magic-stick-2-bold-duotone class="provider-icon size-6"
|
||||||
|
transition="filter duration-250 ease-in-out"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
Theme Presets
|
||||||
|
</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 flex="~ col gap-4">
|
||||||
|
<div
|
||||||
|
v-for="preset in colorPresets"
|
||||||
|
:key="preset.name"
|
||||||
|
flex="~ row"
|
||||||
|
bg="neutral-100 dark:neutral-800"
|
||||||
|
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||||
|
transition="all ease-in-out duration-250"
|
||||||
|
cursor-pointer items-center justify-between gap-4 rounded-lg px-4 py-3
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div text-base font-medium>
|
||||||
|
{{ preset.name }}
|
||||||
|
</div>
|
||||||
|
<div text="sm neutral-500">
|
||||||
|
{{ preset.description }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div flex="~ row" gap-2>
|
||||||
|
<TooltipProvider v-for="color in preset.colors" :key="color.hex">
|
||||||
|
<TooltipRoot>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<div
|
||||||
|
:style="{ backgroundColor: color.hex }"
|
||||||
|
class="size-6 cursor-pointer rounded-full transition-all duration-250 ease-in-out" :class="[
|
||||||
|
isColorSelected(color.hex)
|
||||||
|
? 'scale-150 z-10 mx-1'
|
||||||
|
: 'hover:scale-110',
|
||||||
|
]"
|
||||||
|
@click="applyPrimaryColorFromHex(color.hex)"
|
||||||
|
/>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipContent class="rounded-lg bg-white px-3 py-1.5 text-sm shadow-md dark:bg-neutral-800">
|
||||||
|
{{ color.name }}
|
||||||
|
<TooltipArrow class="fill-white dark:fill-neutral-800" />
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</TooltipRoot>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Collapsable>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
|
<div text="40" i-lucide:paintbrush />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.primary-color-bar {
|
.primary-color-bar {
|
||||||
@apply w-full h-full flex-1 flex items-center justify-center;
|
--at-apply: w-full h-full flex-1 flex items-center justify-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-hue-slider {
|
.theme-hue-slider {
|
||||||
@apply flex-1 w-32 h-2 rounded-full appearance-none;
|
--at-apply: rounded-lg appearance-none;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
oklch(85% 0.2 0),
|
oklch(85% 0.2 0),
|
||||||
@@ -184,6 +382,16 @@ function resetToDefault() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-hue-slider::-webkit-slider-thumb {
|
||||||
|
--at-apply: w-2 h-12 appearance-none rounded-md bg-neutral-500/80 dark: bg-neutral-400/80 cursor-pointer shadow-md
|
||||||
|
border-2 border-white hover: bg-neutral-500 dark: hover: bg-neutral-400 transition-colors duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-hue-slider::-moz-range-thumb {
|
||||||
|
--at-apply: w-2 h-12 bg-neutral-500/80 rounded-md dark: bg-neutral-400/80 cursor-pointer shadow-md border-2
|
||||||
|
border-white border-box hover: bg-neutral-500 dark: hover: bg-neutral-400 transition-colors duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
.transparency-grid {
|
.transparency-grid {
|
||||||
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
|
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
|
||||||
linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%),
|
linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%),
|
||||||
@@ -197,3 +405,9 @@ function resetToDefault() {
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
stageTransition:
|
||||||
|
name: slide
|
||||||
|
</route>
|
||||||
|
|||||||
@@ -140,8 +140,8 @@ function handleLanguageChange(event: Event) {
|
|||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0>
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:cog translate-x-10 translate-y-10 />
|
<div v-motion text="40" i-lucide:cog />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ const router = useRouter()
|
|||||||
<Live2DSettings w="50%" h="80vh" />
|
<Live2DSettings w="50%" h="80vh" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:person-standing translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:person-standing />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ function updateCustomModelName(value: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 class="text-neutral-100/80 dark:text-neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:ghost translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:ghost />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ const modulesList = computed<Module[]>(() => [
|
|||||||
:configured="module.configured"
|
:configured="module.configured"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:blocks translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:blocks />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ function updateSSMLExample() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 class="text-neutral-100/80 dark:text-neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:volume-2 translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:volume-2 />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ function handleResetVoiceSettings() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" :class="providerMetadata?.icon" translate-x-10 translate-y-10 />
|
<div text="40" :class="providerMetadata?.icon" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ const { allProvidersMetadata } = storeToRefs(providersStore)
|
|||||||
:configured="provider.configured"
|
:configured="provider.configured"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:brain translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:brain />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ watch([apiKey, baseUrl], () => {
|
|||||||
</Collapsable>
|
</Collapsable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lobe-icons:openai translate-x-10 translate-y-10 />
|
<div text="40" i-lobe-icons:openai />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ watch([apiKey, baseUrl], () => {
|
|||||||
</Collapsable>
|
</Collapsable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div fixed bottom-0 right-0 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" :class="providerMetadata?.icon" translate-x-10 translate-y-10 />
|
<div text="40" :class="providerMetadata?.icon" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -358,8 +358,8 @@ function isColorSelected(hexColor: string): boolean {
|
|||||||
</Collapsable>
|
</Collapsable>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fixed bottom-0 right-0 z--1 text="neutral-100/80 dark:neutral-500/20">
|
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
|
||||||
<div text="40" i-lucide:paintbrush translate-x-10 translate-y-10 />
|
<div text="40" i-lucide:paintbrush />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user