diff --git a/package.json b/package.json
index 036ee8d..8bc3d67 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"dependencies": {
"@prisma/client": "^5.22.0",
"@types/node": "^22.10.1",
+ "argon2": "^0.41.1",
"prisma": "^5.22.0",
"redis": "^4.7.0",
"svelte-radix": "^2.0.1"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f8244bc..5cf6b15 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,6 +14,9 @@ importers:
'@types/node':
specifier: ^22.10.1
version: 22.10.1
+ argon2:
+ specifier: ^0.41.1
+ version: 0.41.1
prisma:
specifier: ^5.22.0
version: 5.22.0
@@ -344,6 +347,10 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
+ '@phc/format@1.0.0':
+ resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==}
+ engines: {node: '>=10'}
+
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -647,6 +654,10 @@ packages:
arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ argon2@0.41.1:
+ resolution: {integrity: sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==}
+ engines: {node: '>=16.17.0'}
+
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -1141,6 +1152,14 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ node-addon-api@8.3.0:
+ resolution: {integrity: sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==}
+ engines: {node: ^18 || ^20 || >= 21}
+
+ node-gyp-build@4.8.4:
+ resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
+ hasBin: true
+
node-releases@2.0.18:
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
@@ -1844,6 +1863,8 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1
+ '@phc/format@1.0.0': {}
+
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -2133,6 +2154,12 @@ snapshots:
arg@5.0.2: {}
+ argon2@0.41.1:
+ dependencies:
+ '@phc/format': 1.0.0
+ node-addon-api: 8.3.0
+ node-gyp-build: 4.8.4
+
argparse@2.0.1: {}
aria-query@5.3.2: {}
@@ -2619,6 +2646,10 @@ snapshots:
natural-compare@1.4.0: {}
+ node-addon-api@8.3.0: {}
+
+ node-gyp-build@4.8.4: {}
+
node-releases@2.0.18: {}
normalize-path@3.0.0: {}
diff --git a/src/lib/components/ui/tabs/index.ts b/src/lib/components/ui/tabs/index.ts
new file mode 100644
index 0000000..f1ab372
--- /dev/null
+++ b/src/lib/components/ui/tabs/index.ts
@@ -0,0 +1,18 @@
+import { Tabs as TabsPrimitive } from "bits-ui";
+import Content from "./tabs-content.svelte";
+import List from "./tabs-list.svelte";
+import Trigger from "./tabs-trigger.svelte";
+
+const Root = TabsPrimitive.Root;
+
+export {
+ Root,
+ Content,
+ List,
+ Trigger,
+ //
+ Root as Tabs,
+ Content as TabsContent,
+ List as TabsList,
+ Trigger as TabsTrigger,
+};
diff --git a/src/lib/components/ui/tabs/tabs-content.svelte b/src/lib/components/ui/tabs/tabs-content.svelte
new file mode 100644
index 0000000..b611559
--- /dev/null
+++ b/src/lib/components/ui/tabs/tabs-content.svelte
@@ -0,0 +1,21 @@
+
+
+