From 5ffabe01e291112481a579ec80551d7cd247679b Mon Sep 17 00:00:00 2001 From: Andrei Hudalla <46633092+paranoidPhantom@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:16:34 +0300 Subject: [PATCH 1/5] chore(auth): add nuxt module --- nuxt.config.ts | 25 +- package-lock.json | 599 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 613 insertions(+), 12 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index c6930f6..168fec5 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -53,17 +53,18 @@ export default defineNuxtConfig({ pageTransition: { name: "page", mode: "out-in" }, }, modules: [ - "@nuxt/eslint", - "@nuxt/content", - "@nuxt/fonts", - "@nuxtjs/color-mode", - "shadcn-nuxt", - "@vueuse/nuxt", - "@nuxt/icon", - "@nuxt/scripts", - // "nuxt-studio", - "@nuxtjs/seo", - "nuxt-posthog", + "@nuxt/eslint", + "@nuxt/content", + "@nuxt/fonts", + "@nuxtjs/color-mode", + "shadcn-nuxt", + "@vueuse/nuxt", + "@nuxt/icon", + "@nuxt/scripts", + // "nuxt-studio", + "@nuxtjs/seo", + "nuxt-posthog", + "nuxt-auth-utils", ], site: { name: "Конспекты", @@ -84,4 +85,4 @@ export default defineNuxtConfig({ colorMode: { classSuffix: "", }, -}); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0e44119..bd7e50d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,8 @@ "lucide-vue-next": "^0.553.0", "motion-v": "^1.7.4", "nuxt": "^4.2.1", + "nuxt-auth-utils": "^0.5.25", + "nuxt-posthog": "1.6.3", "ogl": "^1.0.11", "rehype-mathjax": "^7.1.0", "reka-ui": "^2.6.0", @@ -44,6 +46,31 @@ "typescript": "^5.9.3" } }, + "node_modules/@adonisjs/hash": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@adonisjs/hash/-/hash-9.1.1.tgz", + "integrity": "sha512-ZkRguwjAp4skKvKDdRAfdJ2oqQ0N7p9l3sioyXO1E8o0WcsyDgEpsTQtuVNoIdMiw4sn4gJlmL3nyF4BcK1ZDQ==", + "license": "MIT", + "dependencies": { + "@phc/format": "^1.0.0", + "@poppinss/utils": "^6.9.3" + }, + "engines": { + "node": ">=20.6.0" + }, + "peerDependencies": { + "argon2": "^0.31.2 || ^0.41.0 || ^0.43.0", + "bcrypt": "^5.1.1 || ^6.0.0" + }, + "peerDependenciesMeta": { + "argon2": { + "optional": true + }, + "bcrypt": { + "optional": true + } + } + }, "node_modules/@antfu/install-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", @@ -1638,6 +1665,15 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "license": "MIT" }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.0.tgz", @@ -3709,6 +3745,15 @@ "node": ">=0.10" } }, + "node_modules/@phc/format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", + "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3784,6 +3829,57 @@ "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", "license": "MIT" }, + "node_modules/@poppinss/object-builder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@poppinss/object-builder/-/object-builder-1.1.0.tgz", + "integrity": "sha512-FOrOq52l7u8goR5yncX14+k+Ewi5djnrt1JwXeS/FvnwAPOiveFhiczCDuvXdssAwamtrV2hp5Rw9v+n2T7hQg==", + "license": "MIT", + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@poppinss/string": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@poppinss/string/-/string-1.7.0.tgz", + "integrity": "sha512-IuCtWaUwmJeAdby0n1a5cTYsBLe7fPymdc4oNTTl1b6l+Ok+14XpSX0ILOEU6UtZ9D2XI3f4TVUh4Titkk1xgw==", + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "@types/bytes": "^3.1.5", + "@types/pluralize": "^0.0.33", + "bytes": "^3.1.2", + "case-anything": "^3.1.2", + "pluralize": "^8.0.0", + "slugify": "^1.6.6", + "truncatise": "^0.0.8" + } + }, + "node_modules/@poppinss/utils": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-6.10.1.tgz", + "integrity": "sha512-da+MMyeXhBaKtxQiWPfy7+056wk3lVIhioJnXHXkJ2/OHDaZfFcyKHNl1R06sdYO8lIRXcXdoZ6LO2ARmkAREA==", + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.1", + "@poppinss/object-builder": "^1.1.0", + "@poppinss/string": "^1.3.0", + "flattie": "^1.1.1", + "safe-stable-stringify": "^2.5.0", + "secure-json-parse": "^4.0.0" + }, + "engines": { + "node": ">=18.16.0" + } + }, + "node_modules/@posthog/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.6.0.tgz", + "integrity": "sha512-Tbh8UACwbb7jFdDC7wwXHtfNzO+4wKh3VbyMHmp2UBe6w1jliJixexTJNfkqdGZm+ht3M10mcKvGGPnoZ2zLBg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + } + }, "node_modules/@resvg/resvg-js": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.2.tgz", @@ -4958,6 +5054,12 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/bytes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.5.tgz", + "integrity": "sha512-VgZkrJckypj85YxEsEavcMmmSOIzkUHqWmM4CCyia5dc54YwsXzJ5uT4fYxBQNEXx+oF1krlhgCbvfubXqZYsQ==", + "license": "MIT" + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -5036,6 +5138,12 @@ "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", "license": "MIT" }, + "node_modules/@types/pluralize": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.33.tgz", + "integrity": "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==", + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -6398,6 +6506,12 @@ "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.22", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", @@ -6435,6 +6549,17 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/b4a": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", @@ -6747,6 +6872,15 @@ "esbuild": ">=0.18" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/c12": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.2.tgz", @@ -6784,6 +6918,19 @@ "node": ">=8" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -6834,6 +6981,18 @@ ], "license": "CC-BY-4.0" }, + "node_modules/case-anything": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-3.1.2.tgz", + "integrity": "sha512-wljhAjDDIv/hM2FzgJnYQg90AWmZMNtESCjTeLH680qTzdo0nErlCxOmgzgX4ZsZAtIvqHyD87ES8QyriXB+BQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -7199,6 +7358,18 @@ "devOptional": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -7323,6 +7494,17 @@ "iconv-lite": "^0.4.8" } }, + "node_modules/core-js": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.46.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", @@ -7769,6 +7951,15 @@ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", "license": "MIT" }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -7937,6 +8128,20 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -8138,12 +8343,57 @@ "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==", "license": "MIT" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "license": "MIT" }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -9123,6 +9373,35 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "license": "ISC" }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fontaine": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/fontaine/-/fontaine-0.7.0.tgz", @@ -9206,6 +9485,43 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fraction.js": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", @@ -9311,12 +9627,49 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-port-please": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", "license": "MIT" }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -9492,6 +9845,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -9557,6 +9922,33 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -10518,6 +10910,15 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/jose": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.2.tgz", + "integrity": "sha512-MpcPtHLE5EmztuFIqB0vzHAWJPpmN1E6L4oo+kze56LIs3MyXIj9ZHMDxqOvkP38gBR7K1v3jqd4WU2+nrfONQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11273,6 +11674,15 @@ "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", "license": "Apache-2.0" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mathjax-full": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.1.tgz", @@ -12823,6 +13233,45 @@ } } }, + "node_modules/nuxt-auth-utils": { + "version": "0.5.25", + "resolved": "https://registry.npmjs.org/nuxt-auth-utils/-/nuxt-auth-utils-0.5.25.tgz", + "integrity": "sha512-tL9Y0duW3a133BZxy5917KvZ9iLX900PW47Qr80IPytwFspEzyqD7c1/zWACUVPv7QPTTD3LxT7LOtK4aJnfEw==", + "license": "MIT", + "dependencies": { + "@adonisjs/hash": "^9.1.1", + "@nuxt/kit": "^4.1.2", + "defu": "^6.1.4", + "h3": "^1.15.4", + "hookable": "^5.5.3", + "jose": "^6.1.0", + "ofetch": "^1.4.1", + "openid-client": "^6.8.0", + "pathe": "^2.0.3", + "scule": "^1.3.0", + "uncrypto": "^0.1.3" + }, + "peerDependencies": { + "@atproto/api": "^0.13.15", + "@atproto/oauth-client-node": "^0.2.0", + "@simplewebauthn/browser": "^11.0.0", + "@simplewebauthn/server": "^11.0.0" + }, + "peerDependenciesMeta": { + "@atproto/api": { + "optional": true + }, + "@atproto/oauth-client-node": { + "optional": true + }, + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + } + } + }, "node_modules/nuxt-component-meta": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/nuxt-component-meta/-/nuxt-component-meta-0.14.2.tgz", @@ -13187,6 +13636,50 @@ "unplugin": "^2.3.6" } }, + "node_modules/nuxt-posthog": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/nuxt-posthog/-/nuxt-posthog-1.6.3.tgz", + "integrity": "sha512-5uUlBITFMJjIxsAPo3gkB8+Yh5tUFSuBV4RQow2MD6B0uBz6wEACLnF28PGzlltnEHpMP26oUi3Si7qEIjhd7Q==", + "license": "MIT", + "dependencies": { + "@nuxt/kit": "^3.15.4", + "defu": "^6.1.4", + "posthog-js": "^1.217.0", + "posthog-node": "4.4.1" + } + }, + "node_modules/nuxt-posthog/node_modules/@nuxt/kit": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.20.1.tgz", + "integrity": "sha512-TIslaylfI5kd3AxX5qts0qyrIQ9Uq3HAA1bgIIJ+c+zpDfK338YS+YrCWxBBzDMECRCbAS58mqAd2MtJfG1ENA==", + "license": "MIT", + "dependencies": { + "c12": "^3.3.1", + "consola": "^3.4.2", + "defu": "^6.1.4", + "destr": "^2.0.5", + "errx": "^0.1.0", + "exsolve": "^1.0.7", + "ignore": "^7.0.5", + "jiti": "^2.6.1", + "klona": "^2.0.6", + "knitwork": "^1.2.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.1", + "unctx": "^2.4.1", + "untyped": "^2.0.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, "node_modules/nuxt-schema-org": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/nuxt-schema-org/-/nuxt-schema-org-5.0.9.tgz", @@ -13326,6 +13819,15 @@ "node": "^14.16.0 || >=16.10.0" } }, + "node_modules/oauth4webapi": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.3.tgz", + "integrity": "sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/object-deep-merge": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.0.tgz", @@ -13438,6 +13940,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openid-client": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.1.tgz", + "integrity": "sha512-VoYT6enBo6Vj2j3Q5Ec0AezS+9YGzQo1f5Xc42lreMGlfP4ljiXPKVDvCADh+XHCV/bqPu/wWSiCVXbJKvrODw==", + "license": "MIT", + "dependencies": { + "jose": "^6.1.0", + "oauth4webapi": "^3.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -14401,6 +14916,47 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/posthog-js": { + "version": "1.298.1", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.298.1.tgz", + "integrity": "sha512-MynFhC2HO6sg5moUfpkd0s6RzAqcqFX75kjIi4Xrj2Gl0/YQWYvFUgvv8FCpWPKPs2mdvNWYhs+oqJg0BVVHPw==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@posthog/core": "1.6.0", + "core-js": "^3.38.1", + "fflate": "^0.4.8", + "preact": "^10.19.3", + "web-vitals": "^4.2.4" + } + }, + "node_modules/posthog-js/node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "license": "MIT" + }, + "node_modules/posthog-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-4.4.1.tgz", + "integrity": "sha512-o9G9sSvwWITrfSJgIUrPLJd//AYPGJNu5D+pSLxqiBvhUeicc/i639FvU0DPr1OsHiLDE2zHNMmLpa0mw4kBCg==", + "license": "MIT", + "dependencies": { + "axios": "^1.7.4" + }, + "engines": { + "node": ">=15.0.0" + } + }, + "node_modules/preact": { + "version": "10.27.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz", + "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -14522,6 +15078,12 @@ "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", "license": "MIT" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -15372,6 +15934,15 @@ ], "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -15805,6 +16376,22 @@ "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", + "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -17233,6 +17820,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/truncatise": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz", + "integrity": "sha512-cXzueh9pzBCsLzhToB4X4gZCb3KYkrsAcBAX97JnazE74HOl3cpBJYEV7nabHeG/6/WXCU5Yujlde/WPBUwnsg==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -18428,6 +19021,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", + "license": "Apache-2.0" + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 3f36460..e414560 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "lucide-vue-next": "^0.553.0", "motion-v": "^1.7.4", "nuxt": "^4.2.1", + "nuxt-auth-utils": "^0.5.25", "nuxt-posthog": "1.6.3", "ogl": "^1.0.11", "rehype-mathjax": "^7.1.0", From 03fb6b73ca1952674062020b24c204928200642b Mon Sep 17 00:00:00 2001 From: Andrei Hudalla <46633092+paranoidPhantom@users.noreply.github.com> Date: Fri, 28 Nov 2025 00:18:39 +0300 Subject: [PATCH 2/5] feat(auth): add three providers --- server/routes/auth/github.get.ts | 20 ++++++++++++++++++++ server/routes/auth/google.get.ts | 17 +++++++++++++++++ server/routes/auth/yandex.get.ts | 17 +++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 server/routes/auth/github.get.ts create mode 100644 server/routes/auth/google.get.ts create mode 100644 server/routes/auth/yandex.get.ts diff --git a/server/routes/auth/github.get.ts b/server/routes/auth/github.get.ts new file mode 100644 index 0000000..a2573cc --- /dev/null +++ b/server/routes/auth/github.get.ts @@ -0,0 +1,20 @@ +export default defineOAuthGitHubEventHandler({ + config: { + emailRequired: true, + }, + async onSuccess(event, { user }) { + await setUserSession(event, { + user: { + githubId: user.id, + avatarUrl: user.avatar_url, + name: user.name, + }, + }); + return sendRedirect(event, "/"); + }, + // Optional, will return a json error and 401 status code by default + onError(event, error) { + console.error("GitHub OAuth error:", error); + return sendRedirect(event, "/"); + }, +}); diff --git a/server/routes/auth/google.get.ts b/server/routes/auth/google.get.ts new file mode 100644 index 0000000..f36fef6 --- /dev/null +++ b/server/routes/auth/google.get.ts @@ -0,0 +1,17 @@ +export default defineOAuthGoogleEventHandler({ + async onSuccess(event, { user }) { + await setUserSession(event, { + user: { + googleId: user.sub, + avatarUrl: user.picture, + name: `${user.given_name} ${user.family_name ?? ""}`.trim(), + }, + }); + return sendRedirect(event, "/"); + }, + // Optional, will return a json error and 401 status code by default + onError(event, error) { + console.error("Google OAuth error:", error); + return sendRedirect(event, "/"); + }, +}); diff --git a/server/routes/auth/yandex.get.ts b/server/routes/auth/yandex.get.ts new file mode 100644 index 0000000..7f2f8f8 --- /dev/null +++ b/server/routes/auth/yandex.get.ts @@ -0,0 +1,17 @@ +export default defineOAuthYandexEventHandler({ + async onSuccess(event, { user }) { + await setUserSession(event, { + user: { + yandexId: user.id, + avatarUrl: `https://avatars.yandex.net/get-yapic/${user.default_avatar_id}/islands-200`, + name: user.display_name ?? user.real_name, + }, + }); + return sendRedirect(event, "/"); + }, + // Optional, will return a json error and 401 status code by default + onError(event, error) { + console.error("Yandex OAuth error:", error); + return sendRedirect(event, "/"); + }, +}); From 2a4c04281261d109737ea2c8d0acba5ebb8f9469 Mon Sep 17 00:00:00 2001 From: Andrei Hudalla <46633092+paranoidPhantom@users.noreply.github.com> Date: Fri, 28 Nov 2025 14:17:27 +0300 Subject: [PATCH 3/5] chore: ignore vscode config --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4a7f73a..5bdfc11 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ logs .env .env.* !.env.example + +.vscode \ No newline at end of file From 43b8f13c6aab2049936a75261cded7139183b3fa Mon Sep 17 00:00:00 2001 From: Andrei Hudalla <46633092+paranoidPhantom@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:37:59 +0300 Subject: [PATCH 4/5] feat(ui): auth flow --- app/components/AppSidebar.vue | 65 +++++++++++++++++++ app/components/ui/avatar/Avatar.vue | 18 +++++ app/components/ui/avatar/AvatarFallback.vue | 21 ++++++ app/components/ui/avatar/AvatarImage.vue | 16 +++++ app/components/ui/avatar/index.ts | 3 + .../ui/button-group/ButtonGroup.vue | 22 +++++++ .../ui/button-group/ButtonGroupSeparator.vue | 24 +++++++ .../ui/button-group/ButtonGroupText.vue | 29 +++++++++ app/components/ui/button-group/index.ts | 25 +++++++ app/components/ui/item/Item.vue | 27 ++++++++ app/components/ui/item/ItemActions.vue | 17 +++++ app/components/ui/item/ItemContent.vue | 17 +++++ app/components/ui/item/ItemDescription.vue | 21 ++++++ app/components/ui/item/ItemFooter.vue | 17 +++++ app/components/ui/item/ItemGroup.vue | 18 +++++ app/components/ui/item/ItemHeader.vue | 17 +++++ app/components/ui/item/ItemMedia.vue | 21 ++++++ app/components/ui/item/ItemSeparator.vue | 18 +++++ app/components/ui/item/ItemTitle.vue | 17 +++++ app/components/ui/item/index.ts | 54 +++++++++++++++ app/components/ui/popover/Popover.vue | 19 ++++++ app/components/ui/popover/PopoverAnchor.vue | 15 +++++ app/components/ui/popover/PopoverContent.vue | 45 +++++++++++++ app/components/ui/popover/PopoverTrigger.vue | 15 +++++ app/components/ui/popover/index.ts | 4 ++ app/components/ui/separator/Separator.vue | 2 +- app/pages/index.vue | 3 - 27 files changed, 566 insertions(+), 4 deletions(-) create mode 100644 app/components/ui/avatar/Avatar.vue create mode 100644 app/components/ui/avatar/AvatarFallback.vue create mode 100644 app/components/ui/avatar/AvatarImage.vue create mode 100644 app/components/ui/avatar/index.ts create mode 100644 app/components/ui/button-group/ButtonGroup.vue create mode 100644 app/components/ui/button-group/ButtonGroupSeparator.vue create mode 100644 app/components/ui/button-group/ButtonGroupText.vue create mode 100644 app/components/ui/button-group/index.ts create mode 100644 app/components/ui/item/Item.vue create mode 100644 app/components/ui/item/ItemActions.vue create mode 100644 app/components/ui/item/ItemContent.vue create mode 100644 app/components/ui/item/ItemDescription.vue create mode 100644 app/components/ui/item/ItemFooter.vue create mode 100644 app/components/ui/item/ItemGroup.vue create mode 100644 app/components/ui/item/ItemHeader.vue create mode 100644 app/components/ui/item/ItemMedia.vue create mode 100644 app/components/ui/item/ItemSeparator.vue create mode 100644 app/components/ui/item/ItemTitle.vue create mode 100644 app/components/ui/item/index.ts create mode 100644 app/components/ui/popover/Popover.vue create mode 100644 app/components/ui/popover/PopoverAnchor.vue create mode 100644 app/components/ui/popover/PopoverContent.vue create mode 100644 app/components/ui/popover/PopoverTrigger.vue create mode 100644 app/components/ui/popover/index.ts diff --git a/app/components/AppSidebar.vue b/app/components/AppSidebar.vue index 5e9617d..6a29023 100644 --- a/app/components/AppSidebar.vue +++ b/app/components/AppSidebar.vue @@ -26,6 +26,26 @@ router.afterEach(() => { }); const nav = useState("navigation"); + +const auth = useUserSession(); + +const authOptions = [ + { + route: "/auth/yandex", + label: "Yandex", + icon: "tabler:brand-yandex", + }, + { + route: "/auth/google", + label: "Google", + icon: "tabler:brand-google", + }, + { + route: "/auth/github", + label: "GitHub", + icon: "tabler:brand-github", + }, +]; diff --git a/app/components/ui/avatar/Avatar.vue b/app/components/ui/avatar/Avatar.vue new file mode 100644 index 0000000..bb7e669 --- /dev/null +++ b/app/components/ui/avatar/Avatar.vue @@ -0,0 +1,18 @@ + + + diff --git a/app/components/ui/avatar/AvatarFallback.vue b/app/components/ui/avatar/AvatarFallback.vue new file mode 100644 index 0000000..16b588a --- /dev/null +++ b/app/components/ui/avatar/AvatarFallback.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/avatar/AvatarImage.vue b/app/components/ui/avatar/AvatarImage.vue new file mode 100644 index 0000000..24a8166 --- /dev/null +++ b/app/components/ui/avatar/AvatarImage.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/ui/avatar/index.ts b/app/components/ui/avatar/index.ts new file mode 100644 index 0000000..cf0e003 --- /dev/null +++ b/app/components/ui/avatar/index.ts @@ -0,0 +1,3 @@ +export { default as Avatar } from "./Avatar.vue" +export { default as AvatarFallback } from "./AvatarFallback.vue" +export { default as AvatarImage } from "./AvatarImage.vue" diff --git a/app/components/ui/button-group/ButtonGroup.vue b/app/components/ui/button-group/ButtonGroup.vue new file mode 100644 index 0000000..9dbef6a --- /dev/null +++ b/app/components/ui/button-group/ButtonGroup.vue @@ -0,0 +1,22 @@ + + + diff --git a/app/components/ui/button-group/ButtonGroupSeparator.vue b/app/components/ui/button-group/ButtonGroupSeparator.vue new file mode 100644 index 0000000..e069dd5 --- /dev/null +++ b/app/components/ui/button-group/ButtonGroupSeparator.vue @@ -0,0 +1,24 @@ + + + diff --git a/app/components/ui/button-group/ButtonGroupText.vue b/app/components/ui/button-group/ButtonGroupText.vue new file mode 100644 index 0000000..c436843 --- /dev/null +++ b/app/components/ui/button-group/ButtonGroupText.vue @@ -0,0 +1,29 @@ + + + diff --git a/app/components/ui/button-group/index.ts b/app/components/ui/button-group/index.ts new file mode 100644 index 0000000..474566f --- /dev/null +++ b/app/components/ui/button-group/index.ts @@ -0,0 +1,25 @@ +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +export { default as ButtonGroup } from "./ButtonGroup.vue" +export { default as ButtonGroupSeparator } from "./ButtonGroupSeparator.vue" +export { default as ButtonGroupText } from "./ButtonGroupText.vue" + +export const buttonGroupVariants = cva( + "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2", + { + variants: { + orientation: { + horizontal: + "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none", + vertical: + "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none", + }, + }, + defaultVariants: { + orientation: "horizontal", + }, + }, +) + +export type ButtonGroupVariants = VariantProps diff --git a/app/components/ui/item/Item.vue b/app/components/ui/item/Item.vue new file mode 100644 index 0000000..0cec259 --- /dev/null +++ b/app/components/ui/item/Item.vue @@ -0,0 +1,27 @@ + + + diff --git a/app/components/ui/item/ItemActions.vue b/app/components/ui/item/ItemActions.vue new file mode 100644 index 0000000..b525712 --- /dev/null +++ b/app/components/ui/item/ItemActions.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/item/ItemContent.vue b/app/components/ui/item/ItemContent.vue new file mode 100644 index 0000000..212d64f --- /dev/null +++ b/app/components/ui/item/ItemContent.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/item/ItemDescription.vue b/app/components/ui/item/ItemDescription.vue new file mode 100644 index 0000000..278e6b8 --- /dev/null +++ b/app/components/ui/item/ItemDescription.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/item/ItemFooter.vue b/app/components/ui/item/ItemFooter.vue new file mode 100644 index 0000000..fd57ccf --- /dev/null +++ b/app/components/ui/item/ItemFooter.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/item/ItemGroup.vue b/app/components/ui/item/ItemGroup.vue new file mode 100644 index 0000000..121a0c2 --- /dev/null +++ b/app/components/ui/item/ItemGroup.vue @@ -0,0 +1,18 @@ + + + diff --git a/app/components/ui/item/ItemHeader.vue b/app/components/ui/item/ItemHeader.vue new file mode 100644 index 0000000..c9fb17a --- /dev/null +++ b/app/components/ui/item/ItemHeader.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/item/ItemMedia.vue b/app/components/ui/item/ItemMedia.vue new file mode 100644 index 0000000..db229f3 --- /dev/null +++ b/app/components/ui/item/ItemMedia.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/item/ItemSeparator.vue b/app/components/ui/item/ItemSeparator.vue new file mode 100644 index 0000000..21065d2 --- /dev/null +++ b/app/components/ui/item/ItemSeparator.vue @@ -0,0 +1,18 @@ + + + diff --git a/app/components/ui/item/ItemTitle.vue b/app/components/ui/item/ItemTitle.vue new file mode 100644 index 0000000..81c0827 --- /dev/null +++ b/app/components/ui/item/ItemTitle.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/item/index.ts b/app/components/ui/item/index.ts new file mode 100644 index 0000000..948421d --- /dev/null +++ b/app/components/ui/item/index.ts @@ -0,0 +1,54 @@ +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +export { default as Item } from "./Item.vue" +export { default as ItemActions } from "./ItemActions.vue" +export { default as ItemContent } from "./ItemContent.vue" +export { default as ItemDescription } from "./ItemDescription.vue" +export { default as ItemFooter } from "./ItemFooter.vue" +export { default as ItemGroup } from "./ItemGroup.vue" +export { default as ItemHeader } from "./ItemHeader.vue" +export { default as ItemMedia } from "./ItemMedia.vue" +export { default as ItemSeparator } from "./ItemSeparator.vue" +export { default as ItemTitle } from "./ItemTitle.vue" + +export const itemVariants = cva( + "group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + { + variants: { + variant: { + default: "bg-transparent", + outline: "border-border", + muted: "bg-muted/50", + }, + size: { + default: "p-4 gap-4 ", + sm: "py-3 px-4 gap-2.5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +) + +export const itemMediaVariants = cva( + "flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5", + { + variants: { + variant: { + default: "bg-transparent", + icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4", + image: + "size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +) + +export type ItemVariants = VariantProps +export type ItemMediaVariants = VariantProps diff --git a/app/components/ui/popover/Popover.vue b/app/components/ui/popover/Popover.vue new file mode 100644 index 0000000..4efdb98 --- /dev/null +++ b/app/components/ui/popover/Popover.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/ui/popover/PopoverAnchor.vue b/app/components/ui/popover/PopoverAnchor.vue new file mode 100644 index 0000000..49e01db --- /dev/null +++ b/app/components/ui/popover/PopoverAnchor.vue @@ -0,0 +1,15 @@ + + + diff --git a/app/components/ui/popover/PopoverContent.vue b/app/components/ui/popover/PopoverContent.vue new file mode 100644 index 0000000..cf1e55c --- /dev/null +++ b/app/components/ui/popover/PopoverContent.vue @@ -0,0 +1,45 @@ + + + diff --git a/app/components/ui/popover/PopoverTrigger.vue b/app/components/ui/popover/PopoverTrigger.vue new file mode 100644 index 0000000..fd3b497 --- /dev/null +++ b/app/components/ui/popover/PopoverTrigger.vue @@ -0,0 +1,15 @@ + + + diff --git a/app/components/ui/popover/index.ts b/app/components/ui/popover/index.ts new file mode 100644 index 0000000..66edf89 --- /dev/null +++ b/app/components/ui/popover/index.ts @@ -0,0 +1,4 @@ +export { default as Popover } from "./Popover.vue" +export { default as PopoverAnchor } from "./PopoverAnchor.vue" +export { default as PopoverContent } from "./PopoverContent.vue" +export { default as PopoverTrigger } from "./PopoverTrigger.vue" diff --git a/app/components/ui/separator/Separator.vue b/app/components/ui/separator/Separator.vue index 5429089..78d60ec 100644 --- a/app/components/ui/separator/Separator.vue +++ b/app/components/ui/separator/Separator.vue @@ -17,7 +17,7 @@ const delegatedProps = reactiveOmit(props, "class")