feat(stage-tamagotchi): improved weather widget

This commit is contained in:
Neko Ayaka
2026-01-07 02:40:45 +08:00
parent c69efa6f1a
commit 51b91b8e3d
10 changed files with 315 additions and 27 deletions
+1
View File
@@ -111,6 +111,7 @@
"@iconify-json/svg-spinners": "^1.2.4",
"@iconify-json/vscode-icons": "^1.2.37",
"@intlify/unplugin-vue-i18n": "^11.0.1",
"@proj-airi/iconify-meteocons": "catalog:",
"@proj-airi/lobe-icons": "^1.0.18",
"@proj-airi/unplugin-fetch": "^0.2.1",
"@proj-airi/unplugin-live2d-sdk": "^0.1.6",
+1
View File
@@ -136,6 +136,7 @@
"@iconify-json/vscode-icons": "^1.2.37",
"@iconify/utils": "^3.1.0",
"@intlify/unplugin-vue-i18n": "^11.0.1",
"@proj-airi/iconify-meteocons": "catalog:",
"@proj-airi/lobe-icons": "^1.0.18",
"@proj-airi/stage-shared": "workspace:^",
"@proj-airi/ui-transitions": "workspace:^",
@@ -27,7 +27,13 @@ const clearWidgets = useElectronEventaInvoke(widgetsClear)
const defaultWeatherProps = {
city: 'Tokyo',
temperature: '15°C',
condition: 'Sunny',
condition: 'Light rain',
high: '18°C',
low: '12°C',
humidity: '72%',
wind: '3 m/s',
precipitation: '40%',
}
}
const form = reactive<FormState>({
@@ -195,7 +195,7 @@ function handleClose() {
</script>
<template>
<div class="h-full w-full p-3">
<div class="h-full w-full">
<div v-if="!widgetId" class="h-full flex items-center justify-center">
<div class="border border-neutral-200/20 rounded-xl bg-neutral-900/40 px-4 py-3 text-sm text-neutral-200/80 backdrop-blur">
Missing widget id. Launch the window via a component call to populate this view.
@@ -214,6 +214,7 @@ function handleClose() {
:key="widget.id"
:title="widget.componentName"
:model-value="widget.componentProps"
:size="widget.size"
v-bind="widget.componentProps"
/>
</div>
@@ -223,7 +224,7 @@ function handleClose() {
</div>
</div>
</div>
<div class="[-webkit-app-region:drag] pointer-events-none absolute left-1/2 top-1 h-[14px] w-[36px] rounded-[10px] bg-[rgba(125,125,125,0.28)] backdrop-blur-[6px] -translate-x-1/2">
<div class="[-webkit-app-region:drag] pointer-events-none absolute left-1/2 top-2 h-[14px] w-[36px] rounded-[10px] bg-[rgba(125,125,125,0.28)] backdrop-blur-[6px] -translate-x-1/2">
<div class="absolute left-1/2 top-1/2 h-[3px] w-4 rounded-full bg-[rgba(255,255,255,0.85)] -translate-x-1/2 -translate-y-1/2" />
</div>
</template>
@@ -1,35 +1,285 @@
<script setup lang="ts">
import ClearDay from '../assets/clear-day.svg'
import { computed } from 'vue'
import Skeleton from './Skeleton.vue'
const props = defineProps<{
propsLoading: boolean
type WeatherEffect = 'rain' | 'snow' | 'thunder' | 'fog' | 'cloudy' | 'none'
type SizePreset = 's' | 'm' | 'l' | { cols?: number, rows?: number }
const props = withDefaults(defineProps<{
propsLoading?: boolean
city?: string
temperature?: string
condition?: string
}>()
icon?: string
conditionCode?: string
isNight?: boolean
effect?: WeatherEffect
size?: SizePreset
high?: string
low?: string
feelsLike?: string
humidity?: string
wind?: string
precipitation?: string
}>(), {
propsLoading: false,
isNight: false,
})
const weatherIconMap = {
'clear-day': { icon: 'i-iconify-meteocons:clear-day-fill', effect: 'none', nightKey: 'clear-night' },
'clear-night': { icon: 'i-iconify-meteocons:clear-night-fill', effect: 'none' },
'partly-cloudy-day': { icon: 'i-iconify-meteocons:partly-cloudy-day-fill', effect: 'cloudy', nightKey: 'partly-cloudy-night' },
'partly-cloudy-night': { icon: 'i-iconify-meteocons:partly-cloudy-night-fill', effect: 'cloudy' },
'cloudy': { icon: 'i-iconify-meteocons:cloudy-fill', effect: 'cloudy' },
'overcast': { icon: 'i-iconify-meteocons:overcast-fill', effect: 'cloudy' },
'rain': { icon: 'i-iconify-meteocons:rain-fill', effect: 'rain' },
'drizzle': { icon: 'i-iconify-meteocons:drizzle-fill', effect: 'rain' },
'extreme-rain': { icon: 'i-iconify-meteocons:extreme-rain-fill', effect: 'rain' },
'thunderstorm': { icon: 'i-iconify-meteocons:thunderstorms-fill', effect: 'thunder' },
'snow': { icon: 'i-iconify-meteocons:snow-fill', effect: 'snow' },
'extreme-snow': { icon: 'i-iconify-meteocons:extreme-snow-fill', effect: 'snow' },
'sleet': { icon: 'i-iconify-meteocons:sleet-fill', effect: 'snow' },
'hail': { icon: 'i-iconify-meteocons:hail-fill', effect: 'snow' },
'fog': { icon: 'i-iconify-meteocons:fog-fill', effect: 'fog' },
'mist': { icon: 'i-iconify-meteocons:mist-fill', effect: 'fog' },
'haze': { icon: 'i-iconify-meteocons:haze-fill', effect: 'fog' },
'dust': { icon: 'i-iconify-meteocons:dust-fill', effect: 'fog' },
'smoke': { icon: 'i-iconify-meteocons:smoke-fill', effect: 'fog' },
'wind': { icon: 'i-iconify-meteocons:wind-fill', effect: 'cloudy' },
'tornado': { icon: 'i-iconify-meteocons:tornado-fill', effect: 'thunder' },
'hurricane': { icon: 'i-iconify-meteocons:hurricane-fill', effect: 'thunder' },
} as Record<string, { icon: string, effect?: WeatherEffect, nightKey?: string }>
const normalizedCondition = computed(() => (props.condition ?? '').toLowerCase().trim())
const normalizedCode = computed(() => (props.conditionCode ?? '').toLowerCase().trim())
const isLarge = computed(() => props.size === 'l')
const conditionMappings: Array<{ keywords: string[], key: string }> = [
{ keywords: ['thunder', 'storm', 'lightning'], key: 'thunderstorm' },
{ keywords: ['hurricane', 'typhoon', 'cyclone'], key: 'hurricane' },
{ keywords: ['tornado'], key: 'tornado' },
{ keywords: ['hail'], key: 'hail' },
{ keywords: ['sleet', 'ice'], key: 'sleet' },
{ keywords: ['snow', 'blizzard', 'flurries'], key: 'snow' },
{ keywords: ['extreme rain', 'heavy rain', 'downpour'], key: 'extreme-rain' },
{ keywords: ['rain', 'shower'], key: 'rain' },
{ keywords: ['drizzle', 'sprinkle'], key: 'drizzle' },
{ keywords: ['fog'], key: 'fog' },
{ keywords: ['mist'], key: 'mist' },
{ keywords: ['haze'], key: 'haze' },
{ keywords: ['dust', 'sand'], key: 'dust' },
{ keywords: ['smoke'], key: 'smoke' },
{ keywords: ['overcast'], key: 'overcast' },
{ keywords: ['cloud'], key: 'cloudy' },
{ keywords: ['partly', 'mostly', 'scattered'], key: 'partly-cloudy-day' },
{ keywords: ['wind', 'breezy', 'gust'], key: 'wind' },
{ keywords: ['clear', 'sun', 'fair'], key: 'clear-day' },
]
function isWeatherIconKey(input: string): input is string {
return input in weatherIconMap
}
const resolvedIconKey = computed<string>(() => {
if (props.icon)
return props.icon
const direct = normalizedCode.value
if (direct && isWeatherIconKey(direct))
return direct
const match = conditionMappings.find(({ keywords }) => keywords.some(keyword => normalizedCondition.value.includes(keyword)))
const fallback: string = props.isNight ? 'clear-night' : 'clear-day'
const baseKey = match?.key ?? fallback
const config = weatherIconMap[baseKey]
if (props.isNight && config.nightKey)
return config.nightKey
return baseKey
})
const resolvedIconClass = computed(() => weatherIconMap[resolvedIconKey.value].icon)
</script>
<template>
<div h-full w-full>
<Skeleton v-if="props.propsLoading" rounded-2xl py-2 pl-3 pr-1 class="grid grid-cols-4 grid-rows-3 max-h-35 gap-2">
<Skeleton animation="wave" class="grid-col-span-3 h-[1lh] w-20% rounded-2xl" />
<div class="col-span-1 row-span-2 h-20 w-20 justify-self-end" />
<Skeleton animation="wave" class="col-span-2 row-span-2 h-full w-20% inline-flex items-end rounded-2xl text-gray-600 font-thin dark:text-gray-300" />
<Skeleton animation="wave" class="col-span-2 row-span-1 h-full w-20% inline-flex items-end justify-self-end rounded-2xl pr-4 text-gray-500 dark:text-gray-400" />
<div :class="['relative', 'h-full', 'w-full', 'font-sans']">
<Skeleton
v-if="props.propsLoading"
:class="['grid', 'grid-cols-4', 'grid-rows-3', 'max-h-35', 'gap-2', 'rounded-2xl', 'py-2', 'pl-3', 'pr-1']"
>
<Skeleton
animation="wave"
:class="['col-span-3', 'h-[1lh]', 'w-20%', 'rounded-2xl']"
/>
<div
:class="['col-span-1', 'row-span-2', 'h-20', 'w-20', 'justify-self-end']"
/>
<Skeleton
animation="wave"
:class="['col-span-2', 'row-span-2', 'h-full', 'w-20%', 'inline-flex', 'items-end', 'rounded-2xl', 'text-gray-600', 'font-thin', 'dark:text-gray-300']"
/>
<Skeleton
animation="wave"
:class="['col-span-2', 'row-span-1', 'h-full', 'w-20%', 'inline-flex', 'items-end', 'justify-self-end', 'rounded-2xl', 'pr-4', 'text-gray-500', 'dark:text-gray-400']"
/>
</Skeleton>
<div v-else bg="blue-100 dark:blue-900" rounded-2xl py-2 pl-3 pr-1 class="grid grid-cols-4 grid-rows-3 h-full gap-2">
<div class="grid-col-span-2 text-lg font-semibold">
{{ props.city }}
<div
v-else
:class="[
'relative',
'flex',
'h-full',
'flex-col',
'justify-between',
'gap-3',
'overflow-x-hidden overflow-y-scroll',
'rounded-2xl',
'p-3',
'bg-gradient-to-br',
'from-neutral-950',
'via-neutral-900',
'to-neutral-800',
'text-white',
]"
>
<div
aria-hidden="true"
:class="[
'pointer-events-none',
'absolute',
'-right-8',
'-top-10',
'size-32',
'rounded-full',
'bg-gradient-to-br',
'from-white/30',
'via-white/5',
'to-transparent',
'blur-xl',
]"
/>
<div v-if="isLarge" :class="['relative', 'z-1', 'flex', 'h-full', 'flex-col', 'justify-between', 'gap-4']">
<div :class="['flex', 'items-center', 'justify-center']">
<div
aria-hidden="true"
:class="[
'text-[6rem]',
'leading-none',
'text-white/95',
'drop-shadow-[0_12px_30px_rgba(0,0,0,0.55)]',
resolvedIconClass,
]"
/>
</div>
<div :class="['flex', 'flex-col', 'items-center', 'gap-2']">
<div :class="['text-[4rem]', 'font-semibold', 'leading-none']">
{{ props.temperature ?? '--' }}
</div>
<div :class="['text-lg', 'text-white/85']">
{{ props.condition ?? '—' }}
</div>
<div :class="['text-sm', 'text-white/55']">
{{ props.city ?? 'Unknown' }}
</div>
</div>
<div :class="['h-px', 'w-full', 'bg-white/10']" />
<div :class="['grid', 'grid-cols-3', 'gap-3', 'text-white/80']">
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl', 'leading-none', 'i-iconify-meteocons:wind-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.wind ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Wind
</div>
</div>
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl', 'leading-none', 'i-iconify-meteocons:raindrops-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.precipitation ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Chance of rain
</div>
</div>
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl', 'leading-none', 'i-iconify-meteocons:humidity-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.humidity ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Humidity
</div>
</div>
</div>
</div>
<div v-else :class="['relative', 'z-1', 'flex', 'flex-1', 'flex-col', 'gap-3']">
<div :class="['flex', 'items-start', 'justify-between', 'gap-4', 'flex-1', 'p-2']">
<div
aria-hidden="true"
:class="[
'size-40 scale-120',
'leading-none',
'text-white/90',
'drop-shadow-[0_10px_22px_rgba(0,0,0,0.5)]',
resolvedIconClass,
]"
/>
<div :class="['flex', 'flex-col', 'items-end', 'gap-2']">
<div :class="['text-sm', 'tracking-wide', 'text-white/80']">
{{ props.condition ?? '—' }}
</div>
<div :class="['text-[3.5rem]', 'font-semibold', 'leading-none']">
{{ props.temperature ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
{{ props.city ?? 'Unknown' }}
</div>
</div>
</div>
<div :class="['h-px', 'w-full', 'bg-white/10']" />
<div :class="['grid', 'grid-cols-3', 'gap-2', 'text-white/80', 'flex-shrink-0', 'pb-4']">
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl scale-120', 'leading-none', 'i-iconify-meteocons:wind-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.wind ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Wind
</div>
</div>
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl scale-120', 'leading-none', 'i-iconify-meteocons:raindrops-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.precipitation ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Chance of rain
</div>
</div>
<div :class="['flex', 'flex-col', 'items-center', 'gap-1']">
<div :class="['text-4xl scale-120', 'leading-none', 'i-iconify-meteocons:humidity-fill-static']" />
<div :class="['text-sm', 'font-semibold']">
{{ props.humidity ?? '--' }}
</div>
<div :class="['text-xs', 'text-white/60']">
Humidity
</div>
</div>
<img :src="ClearDay" alt="Weather Icon" class="col-span-2 row-span-2 h-full w-auto justify-self-end">
<div class="col-span-2 row-span-2 h-full inline-flex items-end text-gray-600 font-thin dark:text-gray-300">
<span class="text-[3.5rem] font-thin leading-[1]">{{ props.temperature }}</span>
</div>
<div class="col-span-2 row-span-2 h-full w-full inline-flex items-end justify-end pr-4 text-gray-500 dark:text-gray-400">
<span>{{ props.condition }}</span>
</div>
</div>
</div>
</template>
<style scoped>
</style>
<route lang="yaml">
meta:
layout: plain
</route>
+1
View File
@@ -111,6 +111,7 @@
"@iconify-json/tabler": "catalog:",
"@iconify-json/vscode-icons": "^1.2.37",
"@intlify/unplugin-vue-i18n": "^11.0.1",
"@proj-airi/iconify-meteocons": "catalog:",
"@proj-airi/lobe-icons": "^1.0.18",
"@proj-airi/unplugin-fetch": "^0.2.1",
"@proj-airi/unplugin-live2d-sdk": "^0.1.6",
+1
View File
@@ -164,6 +164,7 @@ words:
- mediabunny
- mediapipe
- MeshToonMaterial
- meteocons
- micvad
- mineflayer
- mingcute
+30 -5
View File
@@ -42,6 +42,9 @@ catalogs:
'@proj-airi/drizzle-duckdb-wasm':
specifier: ^0.4.29
version: 0.4.29
'@proj-airi/iconify-meteocons':
specifier: ^0.1.4
version: 0.1.4
'@types/audioworklet':
specifier: ^0.0.92
version: 0.0.92
@@ -92,7 +95,7 @@ catalogs:
version: 1.4.10
builder-util-runtime:
specifier: ^9.3.1
version: 9.3.1
version: 9.5.1
drizzle-valibot:
specifier: ^0.4.2
version: 0.4.2
@@ -686,6 +689,9 @@ importers:
'@intlify/unplugin-vue-i18n':
specifier: ^11.0.1
version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@2.79.2)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
'@proj-airi/iconify-meteocons':
specifier: 'catalog:'
version: 0.1.4
'@proj-airi/lobe-icons':
specifier: ^1.0.18
version: 1.0.18
@@ -1089,6 +1095,9 @@ importers:
'@intlify/unplugin-vue-i18n':
specifier: ^11.0.1
version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@4.54.0)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
'@proj-airi/iconify-meteocons':
specifier: 'catalog:'
version: 0.1.4
'@proj-airi/lobe-icons':
specifier: ^1.0.18
version: 1.0.18
@@ -1142,7 +1151,7 @@ importers:
version: 0.0.11(electron@39.2.7)(h3@2.0.1-rc.5(crossws@0.4.1(srvx@0.9.8(patch_hash=f0151386fdcbcb6f53833cf8f66926ef2eb31b71a2782d6e0960dec832ef108d))))
builder-util-runtime:
specifier: 'catalog:'
version: 9.3.1
version: 9.5.1
cac:
specifier: ^6.7.14
version: 6.7.14
@@ -1474,6 +1483,9 @@ importers:
'@intlify/unplugin-vue-i18n':
specifier: ^11.0.1
version: 11.0.3(@vue/compiler-dom@3.5.26)(eslint@9.39.2(jiti@2.6.1))(rollup@4.54.0)(typescript@5.9.3)(vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
'@proj-airi/iconify-meteocons':
specifier: 'catalog:'
version: 0.1.4
'@proj-airi/lobe-icons':
specifier: ^1.0.18
version: 1.0.18
@@ -2817,7 +2829,7 @@ importers:
version: 66.5.11
'@wxt-dev/module-vue':
specifier: ^1.0.3
version: 1.0.3(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.54.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
version: 1.0.3(vite@8.0.0-beta.5(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.54.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
vue-tsc:
specifier: ^3.1.8
version: 3.2.1(typescript@5.9.3)
@@ -7212,6 +7224,9 @@ packages:
web-worker:
optional: true
'@proj-airi/iconify-meteocons@0.1.4':
resolution: {integrity: sha512-yliSwluedHb9KCYNuVzlLwSjAUVg5ufMJijqEaXTDrmenwndaIX1Bs3B4jDHQbcwR3hNvrLAlH70SSGCcBXUZA==}
'@proj-airi/lobe-icons@1.0.18':
resolution: {integrity: sha512-Yft/DzWxq5MEChgJKlKXrGASAKBD6tCjr9NvGYvGViyLCHuzgRT6DUdBKKCRXxxI5M99Ilvw+i37kw873YEUpA==}
@@ -20783,6 +20798,10 @@ snapshots:
transitivePeerDependencies:
- '@75lb/nature'
'@proj-airi/iconify-meteocons@0.1.4':
dependencies:
'@iconify/types': 2.0.0
'@proj-airi/lobe-icons@1.0.18':
dependencies:
'@iconify/types': 2.0.0
@@ -22026,6 +22045,12 @@ snapshots:
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)
vue: 3.5.25(typescript@5.9.3)
'@vitejs/plugin-vue@6.0.3(vite@8.0.0-beta.5(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.53
vite: 8.0.0-beta.5(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)
vue: 3.5.25(typescript@5.9.3)
'@vitest/browser-playwright@4.0.16(bufferutil@4.1.0)(playwright@1.57.0)(utf-8-validate@5.0.10)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16)':
dependencies:
'@vitest/browser': 4.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.16)
@@ -22771,9 +22796,9 @@ snapshots:
'@types/filesystem': 0.0.36
'@types/har-format': 1.2.16
'@wxt-dev/module-vue@1.0.3(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.54.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
'@wxt-dev/module-vue@1.0.3(vite@8.0.0-beta.5(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.54.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
dependencies:
'@vitejs/plugin-vue': 6.0.3(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))
'@vitejs/plugin-vue': 6.0.3(vite@8.0.0-beta.5(@types/node@24.10.4)(esbuild@0.25.12)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))
wxt: 0.20.13(@types/node@24.10.4)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.54.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)
transitivePeerDependencies:
- vite
+1
View File
@@ -35,6 +35,7 @@ catalog:
'@nekopaw/tempora': 0.4.0-alpha.1
'@pinia/testing': ^1.0.3
'@proj-airi/drizzle-duckdb-wasm': ^0.4.29
'@proj-airi/iconify-meteocons': ^0.1.4
'@types/audioworklet': ^0.0.92
'@types/hast': ^3.0.4
'@types/splitpanes': ^2.2.6
+1
View File
@@ -135,6 +135,7 @@ export function sharedUnoConfig() {
scale: 1.2,
collections: {
...createExternalPackageIconLoader('@proj-airi/lobe-icons'),
...createExternalPackageIconLoader('@proj-airi/iconify-meteocons'),
},
}),
presetScrollbar(),