feat(stage-ui): extract primary color from stage (#83)

This commit is contained in:
LemonNeko
2025-03-16 21:58:27 +08:00
committed by GitHub
parent 7358023bbb
commit 0463fbb7d1
5 changed files with 447 additions and 3 deletions
+1
View File
@@ -61,6 +61,7 @@
"drizzle-orm": "^0.40.0",
"jszip": "^3.10.1",
"localforage": "^1.10.0",
"node-vibrant": "^4.0.3",
"nprogress": "^0.2.0",
"ofetch": "^1.4.1",
"onnxruntime-web": "^1.21.0",
@@ -3,12 +3,21 @@ import { Collapsable } from '@proj-airi/stage-ui/components'
import { Emotion, EmotionNeutralMotionName } from '@proj-airi/stage-ui/constants'
import { useSettings } from '@proj-airi/stage-ui/stores'
import { useFileDialog, useObjectUrl } from '@vueuse/core'
import { converter } from 'culori'
import JSZip from 'jszip'
import localforage from 'localforage'
import { storeToRefs } from 'pinia'
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
defineProps<{
palette: string[]
}>()
const emit = defineEmits<{
(e: 'extractColorsFromModel'): void
}>()
const { t } = useI18n()
const modelFile = useFileDialog({
@@ -16,7 +25,7 @@ const modelFile = useFileDialog({
})
const settings = useSettings()
const { live2dModelFile, live2dMotionMap, live2dLoadSource, loadingLive2dModel, availableLive2dMotions, live2dModelUrl } = storeToRefs(settings)
const { live2dModelFile, live2dMotionMap, live2dLoadSource, loadingLive2dModel, availableLive2dMotions, live2dModelUrl, themeColorsHue } = storeToRefs(settings)
const localModelUrl = ref(live2dModelUrl.value)
modelFile.onChange((files) => {
@@ -94,6 +103,10 @@ async function saveMotionMap() {
}
const exportObjectUrl = useObjectUrl(live2dModelFile)
function handleHueClick(color: string) {
themeColorsHue.value = converter('oklch')(color)?.h ?? 0
}
</script>
<template>
@@ -171,6 +184,18 @@ const exportObjectUrl = useObjectUrl(live2dModelFile)
{{ t('settings.live2d.change-model.from-file-select') }}
</button>
</div>
<button
bg="zinc-100 dark:zinc-800" hover="bg-zinc-200 dark:bg-zinc-700" w-full
transition="all ease-in-out duration-250"
rounded px-2 py-1 text-sm outline-none @click="emit('extractColorsFromModel')"
>
Extract colors from model
</button>
<div v-if="palette" flex gap-2>
<div v-for="color in palette" :key="color" class="flex items-center gap-1" @click="handleHueClick(color)">
<div size-6 rounded-full :style="{ backgroundColor: color }" />
</div>
</div>
</div>
</div>
</Collapsable>
@@ -2,6 +2,7 @@
import Live2DCanvas from '@proj-airi/stage-ui/components/Live2D/Canvas.vue'
import Live2DModel from '@proj-airi/stage-ui/components/Live2D/Model.vue'
import { useElementBounding } from '@vueuse/core'
import { Vibrant } from 'node-vibrant/browser'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
@@ -9,7 +10,29 @@ import Live2DSettings from '../../../components/Widgets/Live2DSettings.vue'
const router = useRouter()
const live2dContainerRef = ref<HTMLDivElement>()
const live2dCanvasRef = ref<InstanceType<typeof Live2DCanvas>>()
const { width, height } = useElementBounding(live2dContainerRef)
const palette = ref<string[]>([])
async function extractColorsFromModel() {
if (!live2dCanvasRef.value)
return
const frame = await live2dCanvasRef.value.captureFrame()
if (!frame) {
console.error('No frame captured')
return
}
const frameUrl = URL.createObjectURL(frame)
const vibrant = new Vibrant(frameUrl)
const paletteFromVibrant = await vibrant.getPalette()
palette.value = Object.values(paletteFromVibrant).map(color => color?.hex).filter(it => typeof it === 'string')
URL.revokeObjectURL(frameUrl)
}
</script>
<template>
@@ -35,11 +58,11 @@ const { width, height } = useElementBounding(live2dContainerRef)
</div>
<div flex>
<div ref="live2dContainerRef" w="50%" h="80vh">
<Live2DCanvas v-slot="{ app }" :width="width" :height="height">
<Live2DCanvas v-slot="{ app }" ref="live2dCanvasRef" :width="width" :height="height">
<Live2DModel :app="app" :mouth-open-size="0" :width="width" :height="height" :paused="false" />
</Live2DCanvas>
</div>
<Live2DSettings w="50%" h="80vh" />
<Live2DSettings w="50%" h="80vh" :palette="palette" @extract-colors-from-model="extractColorsFromModel" />
</div>
<div text="neutral-100/50 dark:neutral-500/20" pointer-events-none fixed bottom-0 right-0 translate-x-10 translate-y-10>
@@ -23,6 +23,7 @@ async function initLive2DPixiStage(parent: HTMLDivElement) {
width: props.width,
height: props.height,
backgroundAlpha: 0,
preserveDrawingBuffer: true,
})
pixiAppCanvas.value = pixiApp.value.view
@@ -44,6 +45,22 @@ watch([() => props.width, () => props.height], () => handleResize())
onMounted(async () => containerRef.value && await initLive2DPixiStage(containerRef.value))
onUnmounted(() => pixiApp.value?.destroy())
async function captureFrame() {
const frame = new Promise<Blob | null>((resolve) => {
if (!pixiAppCanvas.value || !pixiApp.value)
return resolve(null)
pixiApp.value.render()
pixiAppCanvas.value.toBlob(resolve)
})
return frame
}
defineExpose({
captureFrame,
})
</script>
<template>
+378
View File
@@ -604,6 +604,9 @@ importers:
localforage:
specifier: ^1.10.0
version: 1.10.0
node-vibrant:
specifier: ^4.0.3
version: 4.0.3(encoding@0.1.13)
nprogress:
specifier: ^0.2.0
version: 0.2.0
@@ -3347,6 +3350,50 @@ packages:
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
'@jimp/bmp@0.22.12':
resolution: {integrity: sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/core@0.22.12':
resolution: {integrity: sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA==}
'@jimp/custom@0.22.12':
resolution: {integrity: sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==}
'@jimp/gif@0.22.12':
resolution: {integrity: sha512-y6BFTJgch9mbor2H234VSjd9iwAhaNf/t3US5qpYIs0TSbAvM02Fbc28IaDETj9+4YB4676sz4RcN/zwhfu1pg==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/jpeg@0.22.12':
resolution: {integrity: sha512-Rq26XC/uQWaQKyb/5lksCTCxXhtY01NJeBN+dQv5yNYedN0i7iYu+fXEoRsfaJ8xZzjoANH8sns7rVP4GE7d/Q==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/plugin-resize@0.22.12':
resolution: {integrity: sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/png@0.22.12':
resolution: {integrity: sha512-Mrp6dr3UTn+aLK8ty/dSKELz+Otdz1v4aAXzV5q53UDD2rbB5joKVJ/ChY310B+eRzNxIovbUF1KVrUsYdE8Hg==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/tiff@0.22.12':
resolution: {integrity: sha512-E1LtMh4RyJsoCAfAkBRVSYyZDTtLq9p9LUiiYP0vPtXyxX4BiYBUYihTLSBlCQg5nF2e4OpQg7SPrLdJ66u7jg==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/types@0.22.12':
resolution: {integrity: sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA==}
peerDependencies:
'@jimp/custom': '>=0.3.5'
'@jimp/utils@0.22.12':
resolution: {integrity: sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==}
'@jridgewell/gen-mapping@0.3.5':
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
engines: {node: '>=6.0.0'}
@@ -4395,6 +4442,9 @@ packages:
peerDependencies:
'@testing-library/dom': '>=7.21.4'
'@tokenizer/token@0.3.0':
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
'@tootallnate/once@2.0.0':
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
engines: {node: '>= 10'}
@@ -4641,6 +4691,9 @@ packages:
'@types/node@14.18.63':
resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==}
'@types/node@16.9.1':
resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==}
'@types/node@17.0.45':
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
@@ -4909,6 +4962,39 @@ packages:
peerDependencies:
valibot: ^1.0.0 || ^1.0.0-beta.5 || ^1.0.0-rc
'@vibrant/color@4.0.0':
resolution: {integrity: sha512-S9ItdqS1135wTXoIIqAJu8df9dqlOo6Boc5Y4MGsBTu9UmUOvOwfj5b4Ga6S5yrLAKmKYIactkz7zYJdMddkig==}
'@vibrant/core@4.0.0':
resolution: {integrity: sha512-fqlVRUTDjEws9VNKvI3cDXM4wUT7fMFS+cVqEjJk3im+R5EvjJzPF6OAbNhfPzW04NvHNE555eY9FfhYuX3PRw==}
'@vibrant/generator-default@4.0.3':
resolution: {integrity: sha512-HZlfp19sDokODEkZF4p70QceARHgjP3a1Dmxg+dlblYMJM98jPq+azA0fzqKNR7R17JJNHxexpJEepEsNlG0gw==}
'@vibrant/generator@4.0.0':
resolution: {integrity: sha512-CqKAjmgHVDXJVo3Q5+9pUJOvksR7cN3bzx/6MbURYh7lA4rhsIewkUK155M6q0vfcUN3ETi/eTneCi0tLuM2Sg==}
'@vibrant/image-browser@4.0.0':
resolution: {integrity: sha512-mXckzvJWiP575Y/wNtP87W/TPgyJoGlPBjW4E9YmNS6n4Jb6RqyHQA0ZVulqDslOxjSsihDzY7gpAORRclaoLg==}
'@vibrant/image-node@4.0.0':
resolution: {integrity: sha512-m7yfnQtmo2y8z+tOjRFBx6q/qGnhl/ax2uCaj4TBkm4TtXfR4Dsn90wT6OWXmCFFzxIKHXKKEBShkxR+4RHseA==}
'@vibrant/image@4.0.0':
resolution: {integrity: sha512-Asv/7R/L701norosgvbjOVkodFiwcFihkXixA/gbAd6C+5GCts1Wm1NPk14FNKnM7eKkfAN+0wwPkdOH+PY/YA==}
'@vibrant/quantizer-mmcq@4.0.0':
resolution: {integrity: sha512-TZqNiRoGGyCP8fH1XE6rvhFwLNv9D8MP1Xhz3K8tsuUweC6buWax3qLfrfEnkhtQnPJHaqvTfTOlIIXVMfRpow==}
'@vibrant/quantizer@4.0.0':
resolution: {integrity: sha512-YDGxmCv/RvHFtZghDlVRwH5GMxdGGozWS1JpUOUt73/F5zAKGiiier8F31K1npIXARn6/Gspvg/Rbg7qqyEr2A==}
'@vibrant/types@4.0.0':
resolution: {integrity: sha512-tA5TAbuROXcPkt+PWjmGfoaiEXyySVaNnCZovf6vXhCbMdrTTCQXvNCde2geiVl6YwtuU/Qrj9iZxS5jZ6yVIw==}
'@vibrant/worker@4.0.0':
resolution: {integrity: sha512-nSaZZwWQKOgN/nPYUAIRF0/uoa7KpK91A+gjLmZZDgfN1enqxaiihmn+75ayNadW0c6cxAEpEFEHTONR5u9tMw==}
'@vitejs/plugin-vue@5.2.1':
resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -5454,6 +5540,9 @@ packages:
resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==}
engines: {node: '>=14'}
any-base@1.1.0:
resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
@@ -5674,6 +5763,9 @@ packages:
bluebird@3.7.2:
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
bmp-js@0.1.0:
resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==}
body-parser@1.20.3:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -7176,6 +7268,9 @@ packages:
resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==}
engines: {node: ^18.19.0 || >=20.5.0}
exif-parser@0.1.12:
resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==}
expect-type@1.1.0:
resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
engines: {node: '>=12.0.0'}
@@ -7270,6 +7365,10 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
file-type@16.5.4:
resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==}
engines: {node: '>=10'}
filelist@1.0.4:
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
@@ -7482,6 +7581,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
gifwrap@0.10.1:
resolution: {integrity: sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==}
giget@1.2.3:
resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==}
hasBin: true
@@ -7788,6 +7890,9 @@ packages:
resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==}
engines: {node: '>= 4'}
image-q@4.0.0:
resolution: {integrity: sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==}
image-size@0.5.5:
resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==}
engines: {node: '>=0.10.0'}
@@ -7998,6 +8103,9 @@ packages:
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
engines: {node: '>=16'}
isomorphic-fetch@3.0.0:
resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
@@ -8030,6 +8138,9 @@ packages:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
jpeg-js@0.4.4:
resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -8913,6 +9024,9 @@ packages:
node-rsa@0.4.2:
resolution: {integrity: sha512-Bvso6Zi9LY4otIZefYrscsUpo2mUpiAVIEmSZV2q41sP8tHZoert3Yu6zv4f/RXJqMNZQKCtnhDugIuCma23YA==}
node-vibrant@4.0.3:
resolution: {integrity: sha512-kzoIuJK90BH/k65Avt077JCX4Nhqz1LNc8cIOm2rnYEvFdJIYd8b3SQwU1MTpzcHtr8z8jxkl1qdaCfbP3olFg==}
nopt@5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
engines: {node: '>=6'}
@@ -8997,6 +9111,9 @@ packages:
ohash@2.0.5:
resolution: {integrity: sha512-3k3APZwRRPYyohdIDmPTpe5i0AY5lm7gvu/Oip7tZrTaEGfSlKX+7kXUoWLd9sHX0GDRVwVvlW18yEcD7qS1zw==}
omggif@1.0.10:
resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==}
on-finished@2.3.0:
resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
engines: {node: '>= 0.8'}
@@ -9241,6 +9358,10 @@ packages:
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
engines: {node: '>= 14.16'}
peek-readable@4.1.0:
resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==}
engines: {node: '>=8'}
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@@ -9330,6 +9451,10 @@ packages:
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
engines: {node: '>=0.10.0'}
pixelmatch@4.0.2:
resolution: {integrity: sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==}
hasBin: true
pixi-filters@4.2.0:
resolution: {integrity: sha512-1ImDMPblvy/nafKbl+kACXqWcQY8jixq6ZID1jwcQW5wAEhuKmTtsLv4KU1Ui2qxj8Gor6/WUe3UaqfSR0OYpw==}
@@ -9388,6 +9513,14 @@ packages:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
pngjs@3.4.0:
resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==}
engines: {node: '>=4.0.0'}
pngjs@6.0.0:
resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==}
engines: {node: '>=12.13.0'}
pnpm-workspace-yaml@0.1.2:
resolution: {integrity: sha512-FaSo51Psz+jHV8YtnuIVemTheOIO5EnMtw0HSPTUsASEdOf3ppM5OBxKO5Dpvx4fWKNZF44vEEMFKc5YZG4qjA==}
@@ -9874,6 +10007,14 @@ packages:
resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
readable-stream@4.7.0:
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
readable-web-to-node-stream@3.0.4:
resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==}
engines: {node: '>=8'}
readdir-glob@1.1.3:
resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==}
@@ -9911,6 +10052,9 @@ packages:
regenerate@1.4.2:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
@@ -10486,6 +10630,10 @@ packages:
resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==}
engines: {node: '>=0.10.0'}
strtok3@6.3.0:
resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==}
engines: {node: '>=10'}
style-mod@4.1.2:
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
@@ -10616,9 +10764,15 @@ packages:
through2@0.6.5:
resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==}
timm@1.7.1:
resolution: {integrity: sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==}
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
tinycolor2@1.6.0:
resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==}
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
@@ -10660,6 +10814,10 @@ packages:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
token-types@4.2.1:
resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==}
engines: {node: '>=10'}
toml-eslint-parser@0.10.0:
resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -11134,6 +11292,9 @@ packages:
utf8-byte-length@1.0.5:
resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==}
utif2@4.1.0:
resolution: {integrity: sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==}
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
@@ -11465,6 +11626,9 @@ packages:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
whatwg-fetch@3.6.20:
resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==}
whatwg-mimetype@4.0.0:
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
engines: {node: '>=18'}
@@ -13834,6 +13998,74 @@ snapshots:
'@istanbuljs/schema@0.1.3': {}
'@jimp/bmp@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/utils': 0.22.12
bmp-js: 0.1.0
'@jimp/core@0.22.12(encoding@0.1.13)':
dependencies:
'@jimp/utils': 0.22.12
any-base: 1.1.0
buffer: 5.7.1
exif-parser: 0.1.12
file-type: 16.5.4
isomorphic-fetch: 3.0.0(encoding@0.1.13)
pixelmatch: 4.0.2
tinycolor2: 1.6.0
transitivePeerDependencies:
- encoding
'@jimp/custom@0.22.12(encoding@0.1.13)':
dependencies:
'@jimp/core': 0.22.12(encoding@0.1.13)
transitivePeerDependencies:
- encoding
'@jimp/gif@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/utils': 0.22.12
gifwrap: 0.10.1
omggif: 1.0.10
'@jimp/jpeg@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/utils': 0.22.12
jpeg-js: 0.4.4
'@jimp/plugin-resize@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/utils': 0.22.12
'@jimp/png@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/utils': 0.22.12
pngjs: 6.0.0
'@jimp/tiff@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
utif2: 4.1.0
'@jimp/types@0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))':
dependencies:
'@jimp/bmp': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/gif': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@jimp/jpeg': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@jimp/png': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@jimp/tiff': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
timm: 1.7.1
'@jimp/utils@0.22.12':
dependencies:
regenerator-runtime: 0.13.11
'@jridgewell/gen-mapping@0.3.5':
dependencies:
'@jridgewell/set-array': 1.2.1
@@ -14947,6 +15179,8 @@ snapshots:
dependencies:
'@testing-library/dom': 10.4.0
'@tokenizer/token@0.3.0': {}
'@tootallnate/once@2.0.0': {}
'@tresjs/cientos@4.2.0(@tresjs/core@4.3.3(three@0.174.0)(typescript@5.8.2)(vue@3.5.13(typescript@5.8.2)))(@types/three@0.174.0)(react@18.3.1)(three@0.174.0)(typescript@5.8.2)(vue@3.5.13(typescript@5.8.2))':
@@ -15245,6 +15479,8 @@ snapshots:
'@types/node@14.18.63': {}
'@types/node@16.9.1': {}
'@types/node@17.0.45': {}
'@types/node@18.19.80':
@@ -15645,6 +15881,61 @@ snapshots:
dependencies:
valibot: 1.0.0-beta.9(typescript@5.8.2)
'@vibrant/color@4.0.0': {}
'@vibrant/core@4.0.0':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/generator': 4.0.0
'@vibrant/image': 4.0.0
'@vibrant/quantizer': 4.0.0
'@vibrant/worker': 4.0.0
'@vibrant/generator-default@4.0.3':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/generator': 4.0.0
'@vibrant/generator@4.0.0':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/types': 4.0.0
'@vibrant/image-browser@4.0.0':
dependencies:
'@vibrant/image': 4.0.0
'@vibrant/image-node@4.0.0(encoding@0.1.13)':
dependencies:
'@jimp/custom': 0.22.12(encoding@0.1.13)
'@jimp/plugin-resize': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@jimp/types': 0.22.12(@jimp/custom@0.22.12(encoding@0.1.13))
'@vibrant/image': 4.0.0
transitivePeerDependencies:
- encoding
'@vibrant/image@4.0.0':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/quantizer-mmcq@4.0.0':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/image': 4.0.0
'@vibrant/quantizer': 4.0.0
'@vibrant/quantizer@4.0.0':
dependencies:
'@vibrant/color': 4.0.0
'@vibrant/image': 4.0.0
'@vibrant/types': 4.0.0
'@vibrant/types@4.0.0': {}
'@vibrant/worker@4.0.0':
dependencies:
'@vibrant/types': 4.0.0
'@vitejs/plugin-vue@5.2.1(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.2)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))':
dependencies:
vite: 6.2.2(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.2)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
@@ -16424,6 +16715,8 @@ snapshots:
ansis@3.17.0: {}
any-base@1.1.0: {}
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
@@ -16788,6 +17081,8 @@ snapshots:
bluebird@3.7.2: {}
bmp-js@0.1.0: {}
body-parser@1.20.3:
dependencies:
bytes: 3.1.2
@@ -18633,6 +18928,8 @@ snapshots:
strip-final-newline: 4.0.0
yoctocolors: 2.1.1
exif-parser@0.1.12: {}
expect-type@1.1.0: {}
express-rate-limit@7.5.0(express@5.0.1):
@@ -18798,6 +19095,12 @@ snapshots:
dependencies:
flat-cache: 4.0.1
file-type@16.5.4:
dependencies:
readable-web-to-node-stream: 3.0.4
strtok3: 6.3.0
token-types: 4.2.1
filelist@1.0.4:
dependencies:
minimatch: 5.1.6
@@ -19027,6 +19330,11 @@ snapshots:
fs-extra: 8.1.0
globby: 6.1.0
gifwrap@0.10.1:
dependencies:
image-q: 4.0.0
omggif: 1.0.10
giget@1.2.3:
dependencies:
citty: 0.1.6
@@ -19555,6 +19863,10 @@ snapshots:
ignore@6.0.2:
optional: true
image-q@4.0.0:
dependencies:
'@types/node': 16.9.1
image-size@0.5.5:
optional: true
@@ -19705,6 +20017,13 @@ snapshots:
isexe@3.1.1: {}
isomorphic-fetch@3.0.0(encoding@0.1.13):
dependencies:
node-fetch: 2.7.0(encoding@0.1.13)
whatwg-fetch: 3.6.20
transitivePeerDependencies:
- encoding
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
@@ -19743,6 +20062,8 @@ snapshots:
jiti@2.4.2: {}
jpeg-js@0.4.4: {}
js-tokens@4.0.0: {}
js-tokens@9.0.1: {}
@@ -21015,6 +21336,17 @@ snapshots:
dependencies:
asn1: 0.2.3
node-vibrant@4.0.3(encoding@0.1.13):
dependencies:
'@types/node': 18.19.80
'@vibrant/core': 4.0.0
'@vibrant/generator-default': 4.0.3
'@vibrant/image-browser': 4.0.0
'@vibrant/image-node': 4.0.0(encoding@0.1.13)
'@vibrant/quantizer-mmcq': 4.0.0
transitivePeerDependencies:
- encoding
nopt@5.0.0:
dependencies:
abbrev: 1.1.1
@@ -21099,6 +21431,8 @@ snapshots:
ohash@2.0.5: {}
omggif@1.0.10: {}
on-finished@2.3.0:
dependencies:
ee-first: 1.1.1
@@ -21373,6 +21707,8 @@ snapshots:
pathval@2.0.0: {}
peek-readable@4.1.0: {}
pend@1.2.0: {}
perfect-debounce@1.0.0: {}
@@ -21450,6 +21786,10 @@ snapshots:
pinkie@2.0.4: {}
pixelmatch@4.0.2:
dependencies:
pngjs: 3.4.0
pixi-filters@4.2.0(5af797a0b5bd919a06578c24a7479046):
dependencies:
'@pixi/filter-adjustment': 4.2.0(@pixi/constants@6.5.10)(@pixi/core@6.5.10(@pixi/constants@6.5.10)(@pixi/extensions@6.5.10)(@pixi/math@6.5.10)(@pixi/runner@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))(@pixi/ticker@6.5.10(@pixi/extensions@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10)))(@pixi/utils@6.5.10(@pixi/constants@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))))
@@ -21547,6 +21887,10 @@ snapshots:
pluralize@8.0.0: {}
pngjs@3.4.0: {}
pngjs@6.0.0: {}
pnpm-workspace-yaml@0.1.2:
dependencies:
yaml: 2.7.0
@@ -22134,6 +22478,18 @@ snapshots:
process: 0.11.10
string_decoder: 1.3.0
readable-stream@4.7.0:
dependencies:
abort-controller: 3.0.0
buffer: 6.0.3
events: 3.3.0
process: 0.11.10
string_decoder: 1.3.0
readable-web-to-node-stream@3.0.4:
dependencies:
readable-stream: 4.7.0
readdir-glob@1.1.3:
dependencies:
minimatch: 5.1.6
@@ -22186,6 +22542,8 @@ snapshots:
regenerate@1.4.2: {}
regenerator-runtime@0.13.11: {}
regenerator-runtime@0.14.1: {}
regenerator-transform@0.15.2:
@@ -22932,6 +23290,11 @@ snapshots:
dependencies:
escape-string-regexp: 1.0.5
strtok3@6.3.0:
dependencies:
'@tokenizer/token': 0.3.0
peek-readable: 4.1.0
style-mod@4.1.2: {}
style-to-object@1.0.8:
@@ -23116,8 +23479,12 @@ snapshots:
readable-stream: 1.0.34
xtend: 4.0.2
timm@1.7.1: {}
tinybench@2.9.0: {}
tinycolor2@1.6.0: {}
tinyexec@0.3.2: {}
tinyglobby@0.2.12:
@@ -23149,6 +23516,11 @@ snapshots:
toidentifier@1.0.1: {}
token-types@4.2.1:
dependencies:
'@tokenizer/token': 0.3.0
ieee754: 1.2.1
toml-eslint-parser@0.10.0:
dependencies:
eslint-visitor-keys: 3.4.3
@@ -23799,6 +24171,10 @@ snapshots:
utf8-byte-length@1.0.5: {}
utif2@4.1.0:
dependencies:
pako: 1.0.11
util-deprecate@1.0.2: {}
utils-merge@1.0.1: {}
@@ -24203,6 +24579,8 @@ snapshots:
dependencies:
iconv-lite: 0.6.3
whatwg-fetch@3.6.20: {}
whatwg-mimetype@4.0.0: {}
whatwg-url@14.0.0: