diff --git a/frontend/assets/css/tailwind.css b/frontend/assets/css/tailwind.css index cb6674f..77f3056 100644 --- a/frontend/assets/css/tailwind.css +++ b/frontend/assets/css/tailwind.css @@ -2,6 +2,33 @@ @tailwind components; @tailwind utilities; +/* Fusion Pixel Font - 像素字体 @font-face 声明 */ +/* 下载地址: https://github.com/TakWolf/fusion-pixel-font/releases */ + +@font-face { + font-family: 'Fusion Pixel 12'; + src: url('/fonts/fusion-pixel-12px-monospaced-zh_hans.otf.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Fusion Pixel 10'; + src: url('/fonts/fusion-pixel-10px-monospaced-zh_hans.otf.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Fusion Pixel 8'; + src: url('/fonts/fusion-pixel-8px-monospaced-zh_hans.otf.woff2') format('woff2'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + /* 自定义全局样式 - 微信配色主题 */ @layer base { :root { @@ -10,38 +37,43 @@ --wechat-green-hover: #06ad56; --wechat-green-light: #e6f7f0; --wechat-green-dark: #059341; - + /* 主色调 */ --primary-color: #07c160; --primary-hover: #06ad56; --secondary-color: #4c9e5f; - + /* 危险色 */ --danger-color: #fa5151; --danger-hover: #e94848; - + /* 警告色 */ --warning-color: #ffc300; --warning-hover: #e6ad00; - + /* 背景色 */ --bg-primary: #f7f8fa; --bg-secondary: #ffffff; --bg-gray: #ededed; --bg-dark: #191919; - + /* 文字颜色 */ --text-primary: #191919; --text-secondary: #576b95; --text-light: #888888; --text-white: #ffffff; - + /* 边框颜色 */ --border-color: #e7e7e7; --border-light: #f4f4f4; /* 统一消息圆角(聊天所有消息共用) */ --message-radius: 4px; + + /* Wrapped 年度总结 - 像素字体 */ + --font-pixel-12: 'Fusion Pixel 12', 'Microsoft YaHei', sans-serif; + --font-pixel-10: 'Fusion Pixel 10', 'Microsoft YaHei', sans-serif; + --font-pixel-8: 'Fusion Pixel 8', 'Microsoft YaHei', sans-serif; } body { @@ -80,6 +112,16 @@ /* 统一的消息圆角工具类 */ .msg-radius { border-radius: var(--message-radius); } .msg-bubble { @apply leading-normal break-words text-pretty; border-radius: var(--message-radius); } + + /* 隐私模式(通用):默认模糊,悬停显示 */ + .privacy-blur { + filter: blur(9px); + transition: filter 0.2s ease; + } + + .privacy-blur:hover { + filter: none; + } /* 按钮样式 */ .btn { @apply px-6 py-3 rounded-full font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 transform active:scale-95; @@ -118,6 +160,129 @@ mix-blend-mode: multiply; } + /* Wrapped 增强噪点纹理(动态抖动) */ + .wrapped-noise-enhanced { + background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj4KICA8ZmlsdGVyIGlkPSJuIj4KICAgIDxmZVR1cmJ1bGVuY2UgdHlwZT0iZnJhY3RhbE5vaXNlIiBiYXNlRnJlcXVlbmN5PSIwLjkiIG51bU9jdGF2ZXM9IjUiIHN0aXRjaFRpbGVzPSJzdGl0Y2giLz4KICAgIDxmZUNvbG9yTWF0cml4IHR5cGU9InNhdHVyYXRlIiB2YWx1ZXM9IjAiLz4KICA8L2ZpbHRlcj4KICA8cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsdGVyPSJ1cmwoI24pIiBvcGFjaXR5PSIwLjUiLz4KPC9zdmc+"); + background-repeat: repeat; + background-size: 200px 200px; + mix-blend-mode: multiply; + animation: noise-jitter 0.5s steps(3) infinite; + } + + /* Wrapped 像素字体类 */ + /* Wrapped typography: default is modern; `.wrapped-retro` enables pixel font + CRT vibe. */ + .wrapped-title { + font-weight: 700; + letter-spacing: 0.02em; + } + + .wrapped-title-en { + font-weight: 700; + letter-spacing: 0.04em; + } + + .wrapped-body { + line-height: 1.8; + } + + .wrapped-label { + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; + } + + .wrapped-number { + font-variant-numeric: tabular-nums; + } + + .wrapped-retro .wrapped-title { + font-family: var(--font-pixel-12); + font-weight: normal; + letter-spacing: 0.05em; + image-rendering: pixelated; + -webkit-font-smoothing: none; + } + + .wrapped-retro .wrapped-title-en { + font-family: var(--font-pixel-12); + font-weight: normal; + letter-spacing: 0.08em; + image-rendering: pixelated; + -webkit-font-smoothing: none; + } + + .wrapped-retro .wrapped-body { + font-family: var(--font-pixel-10); + font-weight: normal; + line-height: 1.8; + image-rendering: pixelated; + -webkit-font-smoothing: none; + } + + .wrapped-retro .wrapped-label { + font-family: var(--font-pixel-8); + font-weight: normal; + letter-spacing: 0.15em; + text-transform: uppercase; + image-rendering: pixelated; + -webkit-font-smoothing: none; + } + + .wrapped-retro .wrapped-number { + font-family: var(--font-pixel-12); + font-weight: normal; + font-variant-numeric: tabular-nums; + image-rendering: pixelated; + -webkit-font-smoothing: none; + } + + /* CRT 扫描线 - 水平线条(明显可见) */ + .crt-scanlines { + background: repeating-linear-gradient( + to bottom, + transparent 0px, + transparent 3px, + rgba(0, 0, 0, 0.15) 3px, + rgba(0, 0, 0, 0.15) 4px + ); + background-size: 100% 4px; + animation: scanline-scroll 12s linear infinite; + } + + /* CRT RGB 子像素 - 垂直彩色条纹 */ + .crt-rgb-pixels { + background-image: repeating-linear-gradient( + to right, + rgba(255, 0, 0, 0.06) 0px, + rgba(255, 0, 0, 0.06) 1px, + rgba(0, 255, 0, 0.06) 1px, + rgba(0, 255, 0, 0.06) 2px, + rgba(0, 0, 255, 0.06) 2px, + rgba(0, 0, 255, 0.06) 3px + ); + } + + /* CRT 闪烁 - 亮度波动 */ + .crt-flicker { + background-color: rgba(255, 255, 255, 0.015); + animation: crt-flicker 0.08s infinite alternate; + } + + /* CRT 暗角 - 边缘渐暗(更强) */ + .crt-vignette { + box-shadow: inset 0 0 250px 80px rgba(0, 0, 0, 0.15); + } + + /* CRT 屏幕曲率效果 */ + .crt-curvature { + background: radial-gradient( + ellipse at center, + transparent 0%, + transparent 40%, + rgba(0, 0, 0, 0.1) 100% + ); + } + /* 输入框样式 */ .input { @apply w-full px-4 py-3 bg-[#f7f8fa] border border-transparent rounded-xl focus:outline-none focus:ring-2 focus:ring-[#07c160] focus:bg-white focus:border-[#07c160] transition-all duration-200; @@ -932,3 +1097,53 @@ opacity: 1; } } + +/* CRT 和 Wrapped 动画关键帧 */ +@keyframes scanline-scroll { + 0% { + background-position: 0 0; + } + 100% { + background-position: 0 100vh; + } +} + +@keyframes crt-flicker { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.98; + } +} + +@keyframes noise-jitter { + 0% { + transform: translate(0, 0); + } + 33% { + transform: translate(-1px, 1px); + } + 66% { + transform: translate(1px, -1px); + } + 100% { + transform: translate(0, 0); + } +} + +/* Wrapped 入场动画 */ +@keyframes wrapped-fade-in { + 0% { + opacity: 0; + transform: translateY(20px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.wrapped-animate-in { + animation: wrapped-fade-in 0.6s ease-out forwards; +} diff --git a/frontend/components/wrapped/cards/Card00GlobalOverview.vue b/frontend/components/wrapped/cards/Card00GlobalOverview.vue new file mode 100644 index 0000000..d94916d --- /dev/null +++ b/frontend/components/wrapped/cards/Card00GlobalOverview.vue @@ -0,0 +1,194 @@ + + + diff --git a/frontend/components/wrapped/cards/Card01CyberSchedule.vue b/frontend/components/wrapped/cards/Card01CyberSchedule.vue index a45435f..56e8d68 100644 --- a/frontend/components/wrapped/cards/Card01CyberSchedule.vue +++ b/frontend/components/wrapped/cards/Card01CyberSchedule.vue @@ -1,11 +1,5 @@ + + + diff --git a/frontend/components/wrapped/shared/WrappedCRTOverlay.vue b/frontend/components/wrapped/shared/WrappedCRTOverlay.vue new file mode 100644 index 0000000..a2b8411 --- /dev/null +++ b/frontend/components/wrapped/shared/WrappedCRTOverlay.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend/components/wrapped/shared/WrappedCardShell.vue b/frontend/components/wrapped/shared/WrappedCardShell.vue index 4be81de..37566a3 100644 --- a/frontend/components/wrapped/shared/WrappedCardShell.vue +++ b/frontend/components/wrapped/shared/WrappedCardShell.vue @@ -3,13 +3,12 @@
-
- CARD {{ String(cardId).padStart(2, '0') }} -
-

{{ title }}

-

- {{ narrative }} -

+

{{ title }}

+ +

+ {{ narrative }} +

+
@@ -24,13 +23,12 @@
-
- CARD {{ String(cardId).padStart(2, '0') }} -
-

{{ title }}

-

- {{ narrative }} -

+

{{ title }}

+ +

+ {{ narrative }} +

+
diff --git a/frontend/components/wrapped/shared/WrappedControls.vue b/frontend/components/wrapped/shared/WrappedControls.vue index 4de951f..d7303b1 100644 --- a/frontend/components/wrapped/shared/WrappedControls.vue +++ b/frontend/components/wrapped/shared/WrappedControls.vue @@ -4,9 +4,9 @@
-
账号
+
Account
@@ -34,26 +34,26 @@ :checked="modelRefresh" @change="$emit('update:refresh', !!$event.target.checked)" /> - 强制刷新(忽略缓存) + 强制刷新(忽略缓存)
-
+
{{ showAccount ? '正在加载账号列表...' : '正在检查数据...' }}
-
+
{{ showAccount ? '未发现已解密账号(请先解密数据库)。' : '未发现可用数据(请先解密数据库)。' }}
diff --git a/frontend/components/wrapped/shared/WrappedDeckBackground.vue b/frontend/components/wrapped/shared/WrappedDeckBackground.vue index 14172d5..d30c074 100644 --- a/frontend/components/wrapped/shared/WrappedDeckBackground.vue +++ b/frontend/components/wrapped/shared/WrappedDeckBackground.vue @@ -11,8 +11,8 @@ class="absolute inset-0 bg-[linear-gradient(rgba(7,193,96,0.05)_1px,transparent_1px),linear-gradient(90deg,rgba(7,193,96,0.05)_1px,transparent_1px)] bg-[size:52px_52px] opacity-[0.28]" >
- -
+ +
diff --git a/frontend/components/wrapped/shared/WrappedHero.vue b/frontend/components/wrapped/shared/WrappedHero.vue index a2a90ea..f2b4d39 100644 --- a/frontend/components/wrapped/shared/WrappedHero.vue +++ b/frontend/components/wrapped/shared/WrappedHero.vue @@ -11,26 +11,25 @@ @@ -102,4 +102,12 @@ const legendColor = (i) => { const t = i / 6 return heatColor(Math.max(1, t * (maxValue.value || 1)), maxValue.value || 1) } + +const originFor = (weekdayIndex, hour) => { + // Avoid hover scaling pushing scrollWidth/scrollHeight and showing scrollbars: + // keep the "outer" edges anchored on the first/last row/col. + const x = hour === 0 ? 'left' : (hour === 23 ? 'right' : 'center') + const y = weekdayIndex === 0 ? 'top' : (weekdayIndex === 6 ? 'bottom' : 'center') + return `${x} ${y}` +} diff --git a/frontend/composables/useApi.js b/frontend/composables/useApi.js index 5977948..590379f 100644 --- a/frontend/composables/useApi.js +++ b/frontend/composables/useApi.js @@ -321,6 +321,28 @@ export const useApi = () => { const url = '/wrapped/annual' + (query.toString() ? `?${query.toString()}` : '') return await request(url) } + + // WeChat Wrapped(年度总结)- 目录/元信息(轻量,用于按页懒加载) + const getWrappedAnnualMeta = async (params = {}) => { + const query = new URLSearchParams() + if (params && params.year != null) query.set('year', String(params.year)) + if (params && params.account) query.set('account', String(params.account)) + if (params && params.refresh != null) query.set('refresh', String(!!params.refresh)) + const url = '/wrapped/annual/meta' + (query.toString() ? `?${query.toString()}` : '') + return await request(url) + } + + // WeChat Wrapped(年度总结)- 单张卡片(按页加载) + const getWrappedAnnualCard = async (cardId, params = {}) => { + if (cardId == null) throw new Error('Missing cardId') + const query = new URLSearchParams() + if (params && params.year != null) query.set('year', String(params.year)) + if (params && params.account) query.set('account', String(params.account)) + if (params && params.refresh != null) query.set('refresh', String(!!params.refresh)) + const safeId = encodeURIComponent(String(cardId)) + const url = `/wrapped/annual/cards/${safeId}` + (query.toString() ? `?${query.toString()}` : '') + return await request(url) + } return { detectWechat, @@ -350,6 +372,8 @@ export const useApi = () => { getChatExport, listChatExports, cancelChatExport, - getWrappedAnnual + getWrappedAnnual, + getWrappedAnnualMeta, + getWrappedAnnualCard } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2139597..059c82e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "dependencies": { "@nuxtjs/tailwindcss": "^6.14.0", "@pinia/nuxt": "^0.11.2", + "@vueuse/motion": "^3.0.3", "axios": "^1.11.0", "nuxt": "^4.0.1", "vue": "^3.5.17", @@ -1036,6 +1037,16 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1056,9 +1067,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -3898,6 +3909,12 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", "license": "MIT" }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -4328,6 +4345,114 @@ "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", "license": "MIT" }, + "node_modules/@vueuse/core": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-13.9.0.tgz", + "integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "13.9.0", + "@vueuse/shared": "13.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-13.9.0.tgz", + "integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/motion": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@vueuse/motion/-/motion-3.0.3.tgz", + "integrity": "sha512-4B+ITsxCI9cojikvrpaJcLXyq0spj3sdlzXjzesWdMRd99hhtFI6OJ/1JsqwtF73YooLe0hUn/xDR6qCtmn5GQ==", + "license": "MIT", + "dependencies": { + "@vueuse/core": "^13.0.0", + "@vueuse/shared": "^13.0.0", + "defu": "^6.1.4", + "framesync": "^6.1.2", + "popmotion": "^11.0.5", + "style-value-types": "^5.1.2" + }, + "optionalDependencies": { + "@nuxt/kit": "^3.13.0" + }, + "peerDependencies": { + "vue": ">=3.0.0" + } + }, + "node_modules/@vueuse/motion/node_modules/@nuxt/kit": { + "version": "3.21.0", + "resolved": "https://registry.npmmirror.com/@nuxt/kit/-/kit-3.21.0.tgz", + "integrity": "sha512-KMTLK/dsGaQioZzkYUvgfN9le4grNW54aNcA1jqzgVZLcFVy4jJfrJr5WZio9NT2EMfajdoZ+V28aD7BRr4Zfw==", + "license": "MIT", + "optional": true, + "dependencies": { + "c12": "^3.3.3", + "consola": "^3.4.2", + "defu": "^6.1.4", + "destr": "^2.0.5", + "errx": "^0.1.0", + "exsolve": "^1.0.8", + "ignore": "^7.0.5", + "jiti": "^2.6.1", + "klona": "^2.0.6", + "knitwork": "^1.3.0", + "mlly": "^1.8.0", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2", + "scule": "^1.3.0", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ufo": "^1.6.3", + "unctx": "^2.5.0", + "untyped": "^2.0.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/@vueuse/motion/node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/@vueuse/shared": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-13.9.0.tgz", + "integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, "node_modules/@whatwg-node/disposablestack": { "version": "0.0.6", "resolved": "https://registry.npmmirror.com/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz", @@ -4916,26 +5041,26 @@ } }, "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/c12/-/c12-3.3.3.tgz", + "integrity": "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==", "license": "MIT", "dependencies": { - "chokidar": "^4.0.3", + "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", + "dotenv": "^17.2.3", + "exsolve": "^1.0.8", "giget": "^2.0.0", - "jiti": "^2.4.2", + "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { - "magicast": "^0.3.5" + "magicast": "*" }, "peerDependenciesMeta": { "magicast": { @@ -4943,6 +5068,52 @@ } } }, + "node_modules/c12/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/c12/node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/c12/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", @@ -6583,9 +6754,9 @@ } }, "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", "license": "MIT" }, "node_modules/extract-zip": { @@ -6673,10 +6844,13 @@ } }, "node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6878,6 +7052,21 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framesync": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/framesync/-/framesync-6.1.2.tgz", + "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==", + "license": "MIT", + "dependencies": { + "tslib": "2.4.0" + } + }, + "node_modules/framesync/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/fresh/-/fresh-2.0.0.tgz", @@ -7260,6 +7449,12 @@ "node": ">= 0.4" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", @@ -7842,9 +8037,9 @@ } }, "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "version": "2.6.1", + "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -7944,9 +8139,9 @@ } }, "node_modules/knitwork": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/knitwork/-/knitwork-1.2.0.tgz", - "integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg==", + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/knitwork/-/knitwork-1.3.0.tgz", + "integrity": "sha512-4LqMNoONzR43B1W0ek0fhXMsDNW/zxa1NdFAVMY+k28pgZLovR4G3PB5MrpTxCy1QaZCqNoiaKPr5w5qZHfSNw==", "license": "MIT" }, "node_modules/koa": { @@ -8378,12 +8573,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magic-string-ast": { @@ -8618,15 +8813,15 @@ } }, "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", "license": "MIT", "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" } }, "node_modules/mlly/node_modules/confbox": { @@ -9739,9 +9934,9 @@ } }, "node_modules/pkg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.2.0.tgz", - "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", "license": "MIT", "dependencies": { "confbox": "^0.2.2", @@ -9749,6 +9944,24 @@ "pathe": "^2.0.3" } }, + "node_modules/popmotion": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/popmotion/-/popmotion-11.0.5.tgz", + "integrity": "sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==", + "license": "MIT", + "dependencies": { + "framesync": "6.1.2", + "hey-listen": "^1.0.8", + "style-value-types": "5.1.2", + "tslib": "2.4.0" + } + }, + "node_modules/popmotion/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/portfinder": { "version": "1.0.37", "resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.37.tgz", @@ -11071,9 +11284,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -11584,6 +11797,22 @@ "integrity": "sha512-FL8EeKFFyNQv5cMnXI31CIMCsFarSVI2bF0U0ImeNE3g/F1IvJQyqzOXxPBRXiwQfyBTlbNe88jh1jFW0O/jiQ==", "license": "ISC" }, + "node_modules/style-value-types": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/style-value-types/-/style-value-types-5.1.2.tgz", + "integrity": "sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==", + "license": "MIT", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "2.4.0" + } + }, + "node_modules/style-value-types/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, "node_modules/stylehacks": { "version": "7.0.6", "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-7.0.6.tgz", @@ -12235,9 +12464,9 @@ } }, "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "version": "1.6.3", + "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "license": "MIT" }, "node_modules/ultrahtml": { @@ -12253,15 +12482,15 @@ "license": "MIT" }, "node_modules/unctx": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/unctx/-/unctx-2.4.1.tgz", - "integrity": "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==", + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/unctx/-/unctx-2.5.0.tgz", + "integrity": "sha512-p+Rz9x0R7X+CYDkT+Xg8/GhpcShTlU8n+cf9OtOEf7zEQsNcCZO1dPKNRDqvUTaq+P32PMMkxWHwfrxkqfqAYg==", "license": "MIT", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "estree-walker": "^3.0.3", - "magic-string": "^0.30.17", - "unplugin": "^2.1.0" + "magic-string": "^0.30.21", + "unplugin": "^2.3.11" } }, "node_modules/undici-types": { @@ -12367,13 +12596,14 @@ } }, "node_modules/unplugin": { - "version": "2.3.5", - "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-2.3.5.tgz", - "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==", + "version": "2.3.11", + "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", "license": "MIT", "dependencies": { - "acorn": "^8.14.1", - "picomatch": "^4.0.2", + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" }, "engines": { diff --git a/frontend/package.json b/frontend/package.json index 685e338..ead0715 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "dependencies": { "@nuxtjs/tailwindcss": "^6.14.0", "@pinia/nuxt": "^0.11.2", + "@vueuse/motion": "^3.0.3", "axios": "^1.11.0", "nuxt": "^4.0.1", "vue": "^3.5.17", diff --git a/frontend/pages/wrapped/index.vue b/frontend/pages/wrapped/index.vue index 03ef0fe..ef8b6ae 100644 --- a/frontend/pages/wrapped/index.vue +++ b/frontend/pages/wrapped/index.vue @@ -1,18 +1,96 @@