OhMyDitzzy commited on
Commit
6c75f16
·
1 Parent(s): 948932e
.gitignore ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ # Dependencies
11
+ node_modules
12
+ dist
13
+ dist-ssr
14
+ *.local
15
+
16
+ # Editor
17
+ .vscode/*
18
+ !.vscode/extensions.json
19
+ .idea
20
+ .DS_Store
21
+ *.suo
22
+ *.ntvs*
23
+ *.njsproj
24
+ *.sln
25
+ *.sw?
26
+
27
+ # Environment
28
+ .env
29
+ .env.local
30
+ .env.development.local
31
+ .env.test.local
32
+ .env.production.local
33
+
34
+ # Build
35
+ /dist
36
+ /build
37
+ *.tsbuildinfo
38
+
39
+ # Bun
40
+ .bun
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM oven/bun:1-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package.json ./
6
+ COPY tsconfig.json ./
7
+ COPY tsconfig.node.json ./
8
+ COPY vite.config.ts ./
9
+
10
+ RUN bun install --production
11
+
12
+ COPY src ./src
13
+ COPY public ./public
14
+
15
+ RUN bun install vite @vitejs/plugin-react && bun run build
16
+
17
+ RUN bun build src/server/index.ts --outdir dist --target bun
18
+
19
+ EXPOSE 7860
20
+
21
+ ENV PORT=7860
22
+ ENV NODE_ENV=production
23
+
24
+ # Run the server
25
+ CMD ["bun", "run", "dist/index.js"]
index.html ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="Yuki Botz - Lightweight WhatsApp Bot" />
8
+ <meta name="theme-color" content="#667eea" />
9
+ <title>Yuki Botz</title>
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ <script type="module" src="/src/main.tsx"></script>
14
+ </body>
15
+ </html>
package-lock.json ADDED
@@ -0,0 +1,1846 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "yuki",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "yuki",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "react": "^18.3.1",
12
+ "react-dom": "^18.3.1",
13
+ "react-router-dom": "^6.26.0",
14
+ "ws": "^8.18.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/bun": "^1.3.5",
18
+ "@types/node": "^25.0.3",
19
+ "@types/react": "^18.3.3",
20
+ "@types/react-dom": "^18.3.0",
21
+ "@types/ws": "^8.5.12",
22
+ "@vitejs/plugin-react": "^4.3.1",
23
+ "typescript": "^5.5.3",
24
+ "vite": "^5.4.2"
25
+ }
26
+ },
27
+ "node_modules/@babel/code-frame": {
28
+ "version": "7.27.1",
29
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
30
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
31
+ "dev": true,
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@babel/helper-validator-identifier": "^7.27.1",
35
+ "js-tokens": "^4.0.0",
36
+ "picocolors": "^1.1.1"
37
+ },
38
+ "engines": {
39
+ "node": ">=6.9.0"
40
+ }
41
+ },
42
+ "node_modules/@babel/compat-data": {
43
+ "version": "7.28.5",
44
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
45
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
46
+ "dev": true,
47
+ "license": "MIT",
48
+ "engines": {
49
+ "node": ">=6.9.0"
50
+ }
51
+ },
52
+ "node_modules/@babel/core": {
53
+ "version": "7.28.5",
54
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
55
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
56
+ "dev": true,
57
+ "license": "MIT",
58
+ "peer": true,
59
+ "dependencies": {
60
+ "@babel/code-frame": "^7.27.1",
61
+ "@babel/generator": "^7.28.5",
62
+ "@babel/helper-compilation-targets": "^7.27.2",
63
+ "@babel/helper-module-transforms": "^7.28.3",
64
+ "@babel/helpers": "^7.28.4",
65
+ "@babel/parser": "^7.28.5",
66
+ "@babel/template": "^7.27.2",
67
+ "@babel/traverse": "^7.28.5",
68
+ "@babel/types": "^7.28.5",
69
+ "@jridgewell/remapping": "^2.3.5",
70
+ "convert-source-map": "^2.0.0",
71
+ "debug": "^4.1.0",
72
+ "gensync": "^1.0.0-beta.2",
73
+ "json5": "^2.2.3",
74
+ "semver": "^6.3.1"
75
+ },
76
+ "engines": {
77
+ "node": ">=6.9.0"
78
+ },
79
+ "funding": {
80
+ "type": "opencollective",
81
+ "url": "https://opencollective.com/babel"
82
+ }
83
+ },
84
+ "node_modules/@babel/generator": {
85
+ "version": "7.28.5",
86
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
87
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
88
+ "dev": true,
89
+ "license": "MIT",
90
+ "dependencies": {
91
+ "@babel/parser": "^7.28.5",
92
+ "@babel/types": "^7.28.5",
93
+ "@jridgewell/gen-mapping": "^0.3.12",
94
+ "@jridgewell/trace-mapping": "^0.3.28",
95
+ "jsesc": "^3.0.2"
96
+ },
97
+ "engines": {
98
+ "node": ">=6.9.0"
99
+ }
100
+ },
101
+ "node_modules/@babel/helper-compilation-targets": {
102
+ "version": "7.27.2",
103
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
104
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
105
+ "dev": true,
106
+ "license": "MIT",
107
+ "dependencies": {
108
+ "@babel/compat-data": "^7.27.2",
109
+ "@babel/helper-validator-option": "^7.27.1",
110
+ "browserslist": "^4.24.0",
111
+ "lru-cache": "^5.1.1",
112
+ "semver": "^6.3.1"
113
+ },
114
+ "engines": {
115
+ "node": ">=6.9.0"
116
+ }
117
+ },
118
+ "node_modules/@babel/helper-globals": {
119
+ "version": "7.28.0",
120
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
121
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
122
+ "dev": true,
123
+ "license": "MIT",
124
+ "engines": {
125
+ "node": ">=6.9.0"
126
+ }
127
+ },
128
+ "node_modules/@babel/helper-module-imports": {
129
+ "version": "7.27.1",
130
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
131
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
132
+ "dev": true,
133
+ "license": "MIT",
134
+ "dependencies": {
135
+ "@babel/traverse": "^7.27.1",
136
+ "@babel/types": "^7.27.1"
137
+ },
138
+ "engines": {
139
+ "node": ">=6.9.0"
140
+ }
141
+ },
142
+ "node_modules/@babel/helper-module-transforms": {
143
+ "version": "7.28.3",
144
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
145
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
146
+ "dev": true,
147
+ "license": "MIT",
148
+ "dependencies": {
149
+ "@babel/helper-module-imports": "^7.27.1",
150
+ "@babel/helper-validator-identifier": "^7.27.1",
151
+ "@babel/traverse": "^7.28.3"
152
+ },
153
+ "engines": {
154
+ "node": ">=6.9.0"
155
+ },
156
+ "peerDependencies": {
157
+ "@babel/core": "^7.0.0"
158
+ }
159
+ },
160
+ "node_modules/@babel/helper-plugin-utils": {
161
+ "version": "7.27.1",
162
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
163
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
164
+ "dev": true,
165
+ "license": "MIT",
166
+ "engines": {
167
+ "node": ">=6.9.0"
168
+ }
169
+ },
170
+ "node_modules/@babel/helper-string-parser": {
171
+ "version": "7.27.1",
172
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
173
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
174
+ "dev": true,
175
+ "license": "MIT",
176
+ "engines": {
177
+ "node": ">=6.9.0"
178
+ }
179
+ },
180
+ "node_modules/@babel/helper-validator-identifier": {
181
+ "version": "7.28.5",
182
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
183
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
184
+ "dev": true,
185
+ "license": "MIT",
186
+ "engines": {
187
+ "node": ">=6.9.0"
188
+ }
189
+ },
190
+ "node_modules/@babel/helper-validator-option": {
191
+ "version": "7.27.1",
192
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
193
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
194
+ "dev": true,
195
+ "license": "MIT",
196
+ "engines": {
197
+ "node": ">=6.9.0"
198
+ }
199
+ },
200
+ "node_modules/@babel/helpers": {
201
+ "version": "7.28.4",
202
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
203
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
204
+ "dev": true,
205
+ "license": "MIT",
206
+ "dependencies": {
207
+ "@babel/template": "^7.27.2",
208
+ "@babel/types": "^7.28.4"
209
+ },
210
+ "engines": {
211
+ "node": ">=6.9.0"
212
+ }
213
+ },
214
+ "node_modules/@babel/parser": {
215
+ "version": "7.28.5",
216
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
217
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
218
+ "dev": true,
219
+ "license": "MIT",
220
+ "dependencies": {
221
+ "@babel/types": "^7.28.5"
222
+ },
223
+ "bin": {
224
+ "parser": "bin/babel-parser.js"
225
+ },
226
+ "engines": {
227
+ "node": ">=6.0.0"
228
+ }
229
+ },
230
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
231
+ "version": "7.27.1",
232
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
233
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
234
+ "dev": true,
235
+ "license": "MIT",
236
+ "dependencies": {
237
+ "@babel/helper-plugin-utils": "^7.27.1"
238
+ },
239
+ "engines": {
240
+ "node": ">=6.9.0"
241
+ },
242
+ "peerDependencies": {
243
+ "@babel/core": "^7.0.0-0"
244
+ }
245
+ },
246
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
247
+ "version": "7.27.1",
248
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
249
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
250
+ "dev": true,
251
+ "license": "MIT",
252
+ "dependencies": {
253
+ "@babel/helper-plugin-utils": "^7.27.1"
254
+ },
255
+ "engines": {
256
+ "node": ">=6.9.0"
257
+ },
258
+ "peerDependencies": {
259
+ "@babel/core": "^7.0.0-0"
260
+ }
261
+ },
262
+ "node_modules/@babel/template": {
263
+ "version": "7.27.2",
264
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
265
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
266
+ "dev": true,
267
+ "license": "MIT",
268
+ "dependencies": {
269
+ "@babel/code-frame": "^7.27.1",
270
+ "@babel/parser": "^7.27.2",
271
+ "@babel/types": "^7.27.1"
272
+ },
273
+ "engines": {
274
+ "node": ">=6.9.0"
275
+ }
276
+ },
277
+ "node_modules/@babel/traverse": {
278
+ "version": "7.28.5",
279
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
280
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
281
+ "dev": true,
282
+ "license": "MIT",
283
+ "dependencies": {
284
+ "@babel/code-frame": "^7.27.1",
285
+ "@babel/generator": "^7.28.5",
286
+ "@babel/helper-globals": "^7.28.0",
287
+ "@babel/parser": "^7.28.5",
288
+ "@babel/template": "^7.27.2",
289
+ "@babel/types": "^7.28.5",
290
+ "debug": "^4.3.1"
291
+ },
292
+ "engines": {
293
+ "node": ">=6.9.0"
294
+ }
295
+ },
296
+ "node_modules/@babel/types": {
297
+ "version": "7.28.5",
298
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
299
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
300
+ "dev": true,
301
+ "license": "MIT",
302
+ "dependencies": {
303
+ "@babel/helper-string-parser": "^7.27.1",
304
+ "@babel/helper-validator-identifier": "^7.28.5"
305
+ },
306
+ "engines": {
307
+ "node": ">=6.9.0"
308
+ }
309
+ },
310
+ "node_modules/@esbuild/aix-ppc64": {
311
+ "version": "0.21.5",
312
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
313
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
314
+ "cpu": [
315
+ "ppc64"
316
+ ],
317
+ "dev": true,
318
+ "license": "MIT",
319
+ "optional": true,
320
+ "os": [
321
+ "aix"
322
+ ],
323
+ "engines": {
324
+ "node": ">=12"
325
+ }
326
+ },
327
+ "node_modules/@esbuild/android-arm": {
328
+ "version": "0.21.5",
329
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
330
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
331
+ "cpu": [
332
+ "arm"
333
+ ],
334
+ "dev": true,
335
+ "license": "MIT",
336
+ "optional": true,
337
+ "os": [
338
+ "android"
339
+ ],
340
+ "engines": {
341
+ "node": ">=12"
342
+ }
343
+ },
344
+ "node_modules/@esbuild/android-arm64": {
345
+ "version": "0.21.5",
346
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
347
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
348
+ "cpu": [
349
+ "arm64"
350
+ ],
351
+ "dev": true,
352
+ "license": "MIT",
353
+ "optional": true,
354
+ "os": [
355
+ "android"
356
+ ],
357
+ "engines": {
358
+ "node": ">=12"
359
+ }
360
+ },
361
+ "node_modules/@esbuild/android-x64": {
362
+ "version": "0.21.5",
363
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
364
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
365
+ "cpu": [
366
+ "x64"
367
+ ],
368
+ "dev": true,
369
+ "license": "MIT",
370
+ "optional": true,
371
+ "os": [
372
+ "android"
373
+ ],
374
+ "engines": {
375
+ "node": ">=12"
376
+ }
377
+ },
378
+ "node_modules/@esbuild/darwin-arm64": {
379
+ "version": "0.21.5",
380
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
381
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
382
+ "cpu": [
383
+ "arm64"
384
+ ],
385
+ "dev": true,
386
+ "license": "MIT",
387
+ "optional": true,
388
+ "os": [
389
+ "darwin"
390
+ ],
391
+ "engines": {
392
+ "node": ">=12"
393
+ }
394
+ },
395
+ "node_modules/@esbuild/darwin-x64": {
396
+ "version": "0.21.5",
397
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
398
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
399
+ "cpu": [
400
+ "x64"
401
+ ],
402
+ "dev": true,
403
+ "license": "MIT",
404
+ "optional": true,
405
+ "os": [
406
+ "darwin"
407
+ ],
408
+ "engines": {
409
+ "node": ">=12"
410
+ }
411
+ },
412
+ "node_modules/@esbuild/freebsd-arm64": {
413
+ "version": "0.21.5",
414
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
415
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
416
+ "cpu": [
417
+ "arm64"
418
+ ],
419
+ "dev": true,
420
+ "license": "MIT",
421
+ "optional": true,
422
+ "os": [
423
+ "freebsd"
424
+ ],
425
+ "engines": {
426
+ "node": ">=12"
427
+ }
428
+ },
429
+ "node_modules/@esbuild/freebsd-x64": {
430
+ "version": "0.21.5",
431
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
432
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
433
+ "cpu": [
434
+ "x64"
435
+ ],
436
+ "dev": true,
437
+ "license": "MIT",
438
+ "optional": true,
439
+ "os": [
440
+ "freebsd"
441
+ ],
442
+ "engines": {
443
+ "node": ">=12"
444
+ }
445
+ },
446
+ "node_modules/@esbuild/linux-arm": {
447
+ "version": "0.21.5",
448
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
449
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
450
+ "cpu": [
451
+ "arm"
452
+ ],
453
+ "dev": true,
454
+ "license": "MIT",
455
+ "optional": true,
456
+ "os": [
457
+ "linux"
458
+ ],
459
+ "engines": {
460
+ "node": ">=12"
461
+ }
462
+ },
463
+ "node_modules/@esbuild/linux-arm64": {
464
+ "version": "0.21.5",
465
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
466
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
467
+ "cpu": [
468
+ "arm64"
469
+ ],
470
+ "dev": true,
471
+ "license": "MIT",
472
+ "optional": true,
473
+ "os": [
474
+ "linux"
475
+ ],
476
+ "engines": {
477
+ "node": ">=12"
478
+ }
479
+ },
480
+ "node_modules/@esbuild/linux-ia32": {
481
+ "version": "0.21.5",
482
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
483
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
484
+ "cpu": [
485
+ "ia32"
486
+ ],
487
+ "dev": true,
488
+ "license": "MIT",
489
+ "optional": true,
490
+ "os": [
491
+ "linux"
492
+ ],
493
+ "engines": {
494
+ "node": ">=12"
495
+ }
496
+ },
497
+ "node_modules/@esbuild/linux-loong64": {
498
+ "version": "0.21.5",
499
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
500
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
501
+ "cpu": [
502
+ "loong64"
503
+ ],
504
+ "dev": true,
505
+ "license": "MIT",
506
+ "optional": true,
507
+ "os": [
508
+ "linux"
509
+ ],
510
+ "engines": {
511
+ "node": ">=12"
512
+ }
513
+ },
514
+ "node_modules/@esbuild/linux-mips64el": {
515
+ "version": "0.21.5",
516
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
517
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
518
+ "cpu": [
519
+ "mips64el"
520
+ ],
521
+ "dev": true,
522
+ "license": "MIT",
523
+ "optional": true,
524
+ "os": [
525
+ "linux"
526
+ ],
527
+ "engines": {
528
+ "node": ">=12"
529
+ }
530
+ },
531
+ "node_modules/@esbuild/linux-ppc64": {
532
+ "version": "0.21.5",
533
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
534
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
535
+ "cpu": [
536
+ "ppc64"
537
+ ],
538
+ "dev": true,
539
+ "license": "MIT",
540
+ "optional": true,
541
+ "os": [
542
+ "linux"
543
+ ],
544
+ "engines": {
545
+ "node": ">=12"
546
+ }
547
+ },
548
+ "node_modules/@esbuild/linux-riscv64": {
549
+ "version": "0.21.5",
550
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
551
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
552
+ "cpu": [
553
+ "riscv64"
554
+ ],
555
+ "dev": true,
556
+ "license": "MIT",
557
+ "optional": true,
558
+ "os": [
559
+ "linux"
560
+ ],
561
+ "engines": {
562
+ "node": ">=12"
563
+ }
564
+ },
565
+ "node_modules/@esbuild/linux-s390x": {
566
+ "version": "0.21.5",
567
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
568
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
569
+ "cpu": [
570
+ "s390x"
571
+ ],
572
+ "dev": true,
573
+ "license": "MIT",
574
+ "optional": true,
575
+ "os": [
576
+ "linux"
577
+ ],
578
+ "engines": {
579
+ "node": ">=12"
580
+ }
581
+ },
582
+ "node_modules/@esbuild/linux-x64": {
583
+ "version": "0.21.5",
584
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
585
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
586
+ "cpu": [
587
+ "x64"
588
+ ],
589
+ "dev": true,
590
+ "license": "MIT",
591
+ "optional": true,
592
+ "os": [
593
+ "linux"
594
+ ],
595
+ "engines": {
596
+ "node": ">=12"
597
+ }
598
+ },
599
+ "node_modules/@esbuild/netbsd-x64": {
600
+ "version": "0.21.5",
601
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
602
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
603
+ "cpu": [
604
+ "x64"
605
+ ],
606
+ "dev": true,
607
+ "license": "MIT",
608
+ "optional": true,
609
+ "os": [
610
+ "netbsd"
611
+ ],
612
+ "engines": {
613
+ "node": ">=12"
614
+ }
615
+ },
616
+ "node_modules/@esbuild/openbsd-x64": {
617
+ "version": "0.21.5",
618
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
619
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
620
+ "cpu": [
621
+ "x64"
622
+ ],
623
+ "dev": true,
624
+ "license": "MIT",
625
+ "optional": true,
626
+ "os": [
627
+ "openbsd"
628
+ ],
629
+ "engines": {
630
+ "node": ">=12"
631
+ }
632
+ },
633
+ "node_modules/@esbuild/sunos-x64": {
634
+ "version": "0.21.5",
635
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
636
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
637
+ "cpu": [
638
+ "x64"
639
+ ],
640
+ "dev": true,
641
+ "license": "MIT",
642
+ "optional": true,
643
+ "os": [
644
+ "sunos"
645
+ ],
646
+ "engines": {
647
+ "node": ">=12"
648
+ }
649
+ },
650
+ "node_modules/@esbuild/win32-arm64": {
651
+ "version": "0.21.5",
652
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
653
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
654
+ "cpu": [
655
+ "arm64"
656
+ ],
657
+ "dev": true,
658
+ "license": "MIT",
659
+ "optional": true,
660
+ "os": [
661
+ "win32"
662
+ ],
663
+ "engines": {
664
+ "node": ">=12"
665
+ }
666
+ },
667
+ "node_modules/@esbuild/win32-ia32": {
668
+ "version": "0.21.5",
669
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
670
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
671
+ "cpu": [
672
+ "ia32"
673
+ ],
674
+ "dev": true,
675
+ "license": "MIT",
676
+ "optional": true,
677
+ "os": [
678
+ "win32"
679
+ ],
680
+ "engines": {
681
+ "node": ">=12"
682
+ }
683
+ },
684
+ "node_modules/@esbuild/win32-x64": {
685
+ "version": "0.21.5",
686
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
687
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
688
+ "cpu": [
689
+ "x64"
690
+ ],
691
+ "dev": true,
692
+ "license": "MIT",
693
+ "optional": true,
694
+ "os": [
695
+ "win32"
696
+ ],
697
+ "engines": {
698
+ "node": ">=12"
699
+ }
700
+ },
701
+ "node_modules/@jridgewell/gen-mapping": {
702
+ "version": "0.3.13",
703
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
704
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
705
+ "dev": true,
706
+ "license": "MIT",
707
+ "dependencies": {
708
+ "@jridgewell/sourcemap-codec": "^1.5.0",
709
+ "@jridgewell/trace-mapping": "^0.3.24"
710
+ }
711
+ },
712
+ "node_modules/@jridgewell/remapping": {
713
+ "version": "2.3.5",
714
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
715
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
716
+ "dev": true,
717
+ "license": "MIT",
718
+ "dependencies": {
719
+ "@jridgewell/gen-mapping": "^0.3.5",
720
+ "@jridgewell/trace-mapping": "^0.3.24"
721
+ }
722
+ },
723
+ "node_modules/@jridgewell/resolve-uri": {
724
+ "version": "3.1.2",
725
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
726
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
727
+ "dev": true,
728
+ "license": "MIT",
729
+ "engines": {
730
+ "node": ">=6.0.0"
731
+ }
732
+ },
733
+ "node_modules/@jridgewell/sourcemap-codec": {
734
+ "version": "1.5.5",
735
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
736
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
737
+ "dev": true,
738
+ "license": "MIT"
739
+ },
740
+ "node_modules/@jridgewell/trace-mapping": {
741
+ "version": "0.3.31",
742
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
743
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
744
+ "dev": true,
745
+ "license": "MIT",
746
+ "dependencies": {
747
+ "@jridgewell/resolve-uri": "^3.1.0",
748
+ "@jridgewell/sourcemap-codec": "^1.4.14"
749
+ }
750
+ },
751
+ "node_modules/@remix-run/router": {
752
+ "version": "1.23.2",
753
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
754
+ "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
755
+ "license": "MIT",
756
+ "engines": {
757
+ "node": ">=14.0.0"
758
+ }
759
+ },
760
+ "node_modules/@rolldown/pluginutils": {
761
+ "version": "1.0.0-beta.27",
762
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
763
+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
764
+ "dev": true,
765
+ "license": "MIT"
766
+ },
767
+ "node_modules/@rollup/rollup-android-arm-eabi": {
768
+ "version": "4.55.1",
769
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
770
+ "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
771
+ "cpu": [
772
+ "arm"
773
+ ],
774
+ "dev": true,
775
+ "license": "MIT",
776
+ "optional": true,
777
+ "os": [
778
+ "android"
779
+ ]
780
+ },
781
+ "node_modules/@rollup/rollup-android-arm64": {
782
+ "version": "4.55.1",
783
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
784
+ "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
785
+ "cpu": [
786
+ "arm64"
787
+ ],
788
+ "dev": true,
789
+ "license": "MIT",
790
+ "optional": true,
791
+ "os": [
792
+ "android"
793
+ ]
794
+ },
795
+ "node_modules/@rollup/rollup-darwin-arm64": {
796
+ "version": "4.55.1",
797
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
798
+ "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
799
+ "cpu": [
800
+ "arm64"
801
+ ],
802
+ "dev": true,
803
+ "license": "MIT",
804
+ "optional": true,
805
+ "os": [
806
+ "darwin"
807
+ ]
808
+ },
809
+ "node_modules/@rollup/rollup-darwin-x64": {
810
+ "version": "4.55.1",
811
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
812
+ "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
813
+ "cpu": [
814
+ "x64"
815
+ ],
816
+ "dev": true,
817
+ "license": "MIT",
818
+ "optional": true,
819
+ "os": [
820
+ "darwin"
821
+ ]
822
+ },
823
+ "node_modules/@rollup/rollup-freebsd-arm64": {
824
+ "version": "4.55.1",
825
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
826
+ "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
827
+ "cpu": [
828
+ "arm64"
829
+ ],
830
+ "dev": true,
831
+ "license": "MIT",
832
+ "optional": true,
833
+ "os": [
834
+ "freebsd"
835
+ ]
836
+ },
837
+ "node_modules/@rollup/rollup-freebsd-x64": {
838
+ "version": "4.55.1",
839
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
840
+ "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
841
+ "cpu": [
842
+ "x64"
843
+ ],
844
+ "dev": true,
845
+ "license": "MIT",
846
+ "optional": true,
847
+ "os": [
848
+ "freebsd"
849
+ ]
850
+ },
851
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
852
+ "version": "4.55.1",
853
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
854
+ "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
855
+ "cpu": [
856
+ "arm"
857
+ ],
858
+ "dev": true,
859
+ "license": "MIT",
860
+ "optional": true,
861
+ "os": [
862
+ "linux"
863
+ ]
864
+ },
865
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
866
+ "version": "4.55.1",
867
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
868
+ "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
869
+ "cpu": [
870
+ "arm"
871
+ ],
872
+ "dev": true,
873
+ "license": "MIT",
874
+ "optional": true,
875
+ "os": [
876
+ "linux"
877
+ ]
878
+ },
879
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
880
+ "version": "4.55.1",
881
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
882
+ "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
883
+ "cpu": [
884
+ "arm64"
885
+ ],
886
+ "dev": true,
887
+ "license": "MIT",
888
+ "optional": true,
889
+ "os": [
890
+ "linux"
891
+ ]
892
+ },
893
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
894
+ "version": "4.55.1",
895
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
896
+ "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
897
+ "cpu": [
898
+ "arm64"
899
+ ],
900
+ "dev": true,
901
+ "license": "MIT",
902
+ "optional": true,
903
+ "os": [
904
+ "linux"
905
+ ]
906
+ },
907
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
908
+ "version": "4.55.1",
909
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
910
+ "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
911
+ "cpu": [
912
+ "loong64"
913
+ ],
914
+ "dev": true,
915
+ "license": "MIT",
916
+ "optional": true,
917
+ "os": [
918
+ "linux"
919
+ ]
920
+ },
921
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
922
+ "version": "4.55.1",
923
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
924
+ "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
925
+ "cpu": [
926
+ "loong64"
927
+ ],
928
+ "dev": true,
929
+ "license": "MIT",
930
+ "optional": true,
931
+ "os": [
932
+ "linux"
933
+ ]
934
+ },
935
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
936
+ "version": "4.55.1",
937
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
938
+ "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
939
+ "cpu": [
940
+ "ppc64"
941
+ ],
942
+ "dev": true,
943
+ "license": "MIT",
944
+ "optional": true,
945
+ "os": [
946
+ "linux"
947
+ ]
948
+ },
949
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
950
+ "version": "4.55.1",
951
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
952
+ "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
953
+ "cpu": [
954
+ "ppc64"
955
+ ],
956
+ "dev": true,
957
+ "license": "MIT",
958
+ "optional": true,
959
+ "os": [
960
+ "linux"
961
+ ]
962
+ },
963
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
964
+ "version": "4.55.1",
965
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
966
+ "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
967
+ "cpu": [
968
+ "riscv64"
969
+ ],
970
+ "dev": true,
971
+ "license": "MIT",
972
+ "optional": true,
973
+ "os": [
974
+ "linux"
975
+ ]
976
+ },
977
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
978
+ "version": "4.55.1",
979
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
980
+ "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
981
+ "cpu": [
982
+ "riscv64"
983
+ ],
984
+ "dev": true,
985
+ "license": "MIT",
986
+ "optional": true,
987
+ "os": [
988
+ "linux"
989
+ ]
990
+ },
991
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
992
+ "version": "4.55.1",
993
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
994
+ "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
995
+ "cpu": [
996
+ "s390x"
997
+ ],
998
+ "dev": true,
999
+ "license": "MIT",
1000
+ "optional": true,
1001
+ "os": [
1002
+ "linux"
1003
+ ]
1004
+ },
1005
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
1006
+ "version": "4.55.1",
1007
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
1008
+ "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
1009
+ "cpu": [
1010
+ "x64"
1011
+ ],
1012
+ "dev": true,
1013
+ "license": "MIT",
1014
+ "optional": true,
1015
+ "os": [
1016
+ "linux"
1017
+ ]
1018
+ },
1019
+ "node_modules/@rollup/rollup-linux-x64-musl": {
1020
+ "version": "4.55.1",
1021
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
1022
+ "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
1023
+ "cpu": [
1024
+ "x64"
1025
+ ],
1026
+ "dev": true,
1027
+ "license": "MIT",
1028
+ "optional": true,
1029
+ "os": [
1030
+ "linux"
1031
+ ]
1032
+ },
1033
+ "node_modules/@rollup/rollup-openbsd-x64": {
1034
+ "version": "4.55.1",
1035
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
1036
+ "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
1037
+ "cpu": [
1038
+ "x64"
1039
+ ],
1040
+ "dev": true,
1041
+ "license": "MIT",
1042
+ "optional": true,
1043
+ "os": [
1044
+ "openbsd"
1045
+ ]
1046
+ },
1047
+ "node_modules/@rollup/rollup-openharmony-arm64": {
1048
+ "version": "4.55.1",
1049
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
1050
+ "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
1051
+ "cpu": [
1052
+ "arm64"
1053
+ ],
1054
+ "dev": true,
1055
+ "license": "MIT",
1056
+ "optional": true,
1057
+ "os": [
1058
+ "openharmony"
1059
+ ]
1060
+ },
1061
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
1062
+ "version": "4.55.1",
1063
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
1064
+ "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
1065
+ "cpu": [
1066
+ "arm64"
1067
+ ],
1068
+ "dev": true,
1069
+ "license": "MIT",
1070
+ "optional": true,
1071
+ "os": [
1072
+ "win32"
1073
+ ]
1074
+ },
1075
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
1076
+ "version": "4.55.1",
1077
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
1078
+ "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
1079
+ "cpu": [
1080
+ "ia32"
1081
+ ],
1082
+ "dev": true,
1083
+ "license": "MIT",
1084
+ "optional": true,
1085
+ "os": [
1086
+ "win32"
1087
+ ]
1088
+ },
1089
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
1090
+ "version": "4.55.1",
1091
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
1092
+ "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
1093
+ "cpu": [
1094
+ "x64"
1095
+ ],
1096
+ "dev": true,
1097
+ "license": "MIT",
1098
+ "optional": true,
1099
+ "os": [
1100
+ "win32"
1101
+ ]
1102
+ },
1103
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
1104
+ "version": "4.55.1",
1105
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
1106
+ "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
1107
+ "cpu": [
1108
+ "x64"
1109
+ ],
1110
+ "dev": true,
1111
+ "license": "MIT",
1112
+ "optional": true,
1113
+ "os": [
1114
+ "win32"
1115
+ ]
1116
+ },
1117
+ "node_modules/@types/babel__core": {
1118
+ "version": "7.20.5",
1119
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
1120
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
1121
+ "dev": true,
1122
+ "license": "MIT",
1123
+ "dependencies": {
1124
+ "@babel/parser": "^7.20.7",
1125
+ "@babel/types": "^7.20.7",
1126
+ "@types/babel__generator": "*",
1127
+ "@types/babel__template": "*",
1128
+ "@types/babel__traverse": "*"
1129
+ }
1130
+ },
1131
+ "node_modules/@types/babel__generator": {
1132
+ "version": "7.27.0",
1133
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
1134
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
1135
+ "dev": true,
1136
+ "license": "MIT",
1137
+ "dependencies": {
1138
+ "@babel/types": "^7.0.0"
1139
+ }
1140
+ },
1141
+ "node_modules/@types/babel__template": {
1142
+ "version": "7.4.4",
1143
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
1144
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
1145
+ "dev": true,
1146
+ "license": "MIT",
1147
+ "dependencies": {
1148
+ "@babel/parser": "^7.1.0",
1149
+ "@babel/types": "^7.0.0"
1150
+ }
1151
+ },
1152
+ "node_modules/@types/babel__traverse": {
1153
+ "version": "7.28.0",
1154
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
1155
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
1156
+ "dev": true,
1157
+ "license": "MIT",
1158
+ "dependencies": {
1159
+ "@babel/types": "^7.28.2"
1160
+ }
1161
+ },
1162
+ "node_modules/@types/bun": {
1163
+ "version": "1.3.5",
1164
+ "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.3.5.tgz",
1165
+ "integrity": "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==",
1166
+ "dev": true,
1167
+ "license": "MIT",
1168
+ "dependencies": {
1169
+ "bun-types": "1.3.5"
1170
+ }
1171
+ },
1172
+ "node_modules/@types/estree": {
1173
+ "version": "1.0.8",
1174
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
1175
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
1176
+ "dev": true,
1177
+ "license": "MIT"
1178
+ },
1179
+ "node_modules/@types/node": {
1180
+ "version": "25.0.3",
1181
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
1182
+ "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
1183
+ "dev": true,
1184
+ "license": "MIT",
1185
+ "dependencies": {
1186
+ "undici-types": "~7.16.0"
1187
+ }
1188
+ },
1189
+ "node_modules/@types/prop-types": {
1190
+ "version": "15.7.15",
1191
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
1192
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
1193
+ "dev": true,
1194
+ "license": "MIT"
1195
+ },
1196
+ "node_modules/@types/react": {
1197
+ "version": "18.3.27",
1198
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
1199
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
1200
+ "dev": true,
1201
+ "license": "MIT",
1202
+ "peer": true,
1203
+ "dependencies": {
1204
+ "@types/prop-types": "*",
1205
+ "csstype": "^3.2.2"
1206
+ }
1207
+ },
1208
+ "node_modules/@types/react-dom": {
1209
+ "version": "18.3.7",
1210
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
1211
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
1212
+ "dev": true,
1213
+ "license": "MIT",
1214
+ "peerDependencies": {
1215
+ "@types/react": "^18.0.0"
1216
+ }
1217
+ },
1218
+ "node_modules/@types/ws": {
1219
+ "version": "8.18.1",
1220
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
1221
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
1222
+ "dev": true,
1223
+ "license": "MIT",
1224
+ "dependencies": {
1225
+ "@types/node": "*"
1226
+ }
1227
+ },
1228
+ "node_modules/@vitejs/plugin-react": {
1229
+ "version": "4.7.0",
1230
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
1231
+ "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
1232
+ "dev": true,
1233
+ "license": "MIT",
1234
+ "dependencies": {
1235
+ "@babel/core": "^7.28.0",
1236
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
1237
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
1238
+ "@rolldown/pluginutils": "1.0.0-beta.27",
1239
+ "@types/babel__core": "^7.20.5",
1240
+ "react-refresh": "^0.17.0"
1241
+ },
1242
+ "engines": {
1243
+ "node": "^14.18.0 || >=16.0.0"
1244
+ },
1245
+ "peerDependencies": {
1246
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
1247
+ }
1248
+ },
1249
+ "node_modules/baseline-browser-mapping": {
1250
+ "version": "2.9.12",
1251
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.12.tgz",
1252
+ "integrity": "sha512-Mij6Lij93pTAIsSYy5cyBQ975Qh9uLEc5rwGTpomiZeXZL9yIS6uORJakb3ScHgfs0serMMfIbXzokPMuEiRyw==",
1253
+ "dev": true,
1254
+ "license": "Apache-2.0",
1255
+ "bin": {
1256
+ "baseline-browser-mapping": "dist/cli.js"
1257
+ }
1258
+ },
1259
+ "node_modules/browserslist": {
1260
+ "version": "4.28.1",
1261
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
1262
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
1263
+ "dev": true,
1264
+ "funding": [
1265
+ {
1266
+ "type": "opencollective",
1267
+ "url": "https://opencollective.com/browserslist"
1268
+ },
1269
+ {
1270
+ "type": "tidelift",
1271
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1272
+ },
1273
+ {
1274
+ "type": "github",
1275
+ "url": "https://github.com/sponsors/ai"
1276
+ }
1277
+ ],
1278
+ "license": "MIT",
1279
+ "peer": true,
1280
+ "dependencies": {
1281
+ "baseline-browser-mapping": "^2.9.0",
1282
+ "caniuse-lite": "^1.0.30001759",
1283
+ "electron-to-chromium": "^1.5.263",
1284
+ "node-releases": "^2.0.27",
1285
+ "update-browserslist-db": "^1.2.0"
1286
+ },
1287
+ "bin": {
1288
+ "browserslist": "cli.js"
1289
+ },
1290
+ "engines": {
1291
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1292
+ }
1293
+ },
1294
+ "node_modules/bun-types": {
1295
+ "version": "1.3.5",
1296
+ "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.5.tgz",
1297
+ "integrity": "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==",
1298
+ "dev": true,
1299
+ "license": "MIT",
1300
+ "dependencies": {
1301
+ "@types/node": "*"
1302
+ }
1303
+ },
1304
+ "node_modules/caniuse-lite": {
1305
+ "version": "1.0.30001763",
1306
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001763.tgz",
1307
+ "integrity": "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==",
1308
+ "dev": true,
1309
+ "funding": [
1310
+ {
1311
+ "type": "opencollective",
1312
+ "url": "https://opencollective.com/browserslist"
1313
+ },
1314
+ {
1315
+ "type": "tidelift",
1316
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
1317
+ },
1318
+ {
1319
+ "type": "github",
1320
+ "url": "https://github.com/sponsors/ai"
1321
+ }
1322
+ ],
1323
+ "license": "CC-BY-4.0"
1324
+ },
1325
+ "node_modules/convert-source-map": {
1326
+ "version": "2.0.0",
1327
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
1328
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
1329
+ "dev": true,
1330
+ "license": "MIT"
1331
+ },
1332
+ "node_modules/csstype": {
1333
+ "version": "3.2.3",
1334
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
1335
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
1336
+ "dev": true,
1337
+ "license": "MIT"
1338
+ },
1339
+ "node_modules/debug": {
1340
+ "version": "4.4.3",
1341
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1342
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1343
+ "dev": true,
1344
+ "license": "MIT",
1345
+ "dependencies": {
1346
+ "ms": "^2.1.3"
1347
+ },
1348
+ "engines": {
1349
+ "node": ">=6.0"
1350
+ },
1351
+ "peerDependenciesMeta": {
1352
+ "supports-color": {
1353
+ "optional": true
1354
+ }
1355
+ }
1356
+ },
1357
+ "node_modules/electron-to-chromium": {
1358
+ "version": "1.5.267",
1359
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
1360
+ "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
1361
+ "dev": true,
1362
+ "license": "ISC"
1363
+ },
1364
+ "node_modules/esbuild": {
1365
+ "version": "0.21.5",
1366
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
1367
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
1368
+ "dev": true,
1369
+ "hasInstallScript": true,
1370
+ "license": "MIT",
1371
+ "bin": {
1372
+ "esbuild": "bin/esbuild"
1373
+ },
1374
+ "engines": {
1375
+ "node": ">=12"
1376
+ },
1377
+ "optionalDependencies": {
1378
+ "@esbuild/aix-ppc64": "0.21.5",
1379
+ "@esbuild/android-arm": "0.21.5",
1380
+ "@esbuild/android-arm64": "0.21.5",
1381
+ "@esbuild/android-x64": "0.21.5",
1382
+ "@esbuild/darwin-arm64": "0.21.5",
1383
+ "@esbuild/darwin-x64": "0.21.5",
1384
+ "@esbuild/freebsd-arm64": "0.21.5",
1385
+ "@esbuild/freebsd-x64": "0.21.5",
1386
+ "@esbuild/linux-arm": "0.21.5",
1387
+ "@esbuild/linux-arm64": "0.21.5",
1388
+ "@esbuild/linux-ia32": "0.21.5",
1389
+ "@esbuild/linux-loong64": "0.21.5",
1390
+ "@esbuild/linux-mips64el": "0.21.5",
1391
+ "@esbuild/linux-ppc64": "0.21.5",
1392
+ "@esbuild/linux-riscv64": "0.21.5",
1393
+ "@esbuild/linux-s390x": "0.21.5",
1394
+ "@esbuild/linux-x64": "0.21.5",
1395
+ "@esbuild/netbsd-x64": "0.21.5",
1396
+ "@esbuild/openbsd-x64": "0.21.5",
1397
+ "@esbuild/sunos-x64": "0.21.5",
1398
+ "@esbuild/win32-arm64": "0.21.5",
1399
+ "@esbuild/win32-ia32": "0.21.5",
1400
+ "@esbuild/win32-x64": "0.21.5"
1401
+ }
1402
+ },
1403
+ "node_modules/escalade": {
1404
+ "version": "3.2.0",
1405
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
1406
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
1407
+ "dev": true,
1408
+ "license": "MIT",
1409
+ "engines": {
1410
+ "node": ">=6"
1411
+ }
1412
+ },
1413
+ "node_modules/fsevents": {
1414
+ "version": "2.3.3",
1415
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1416
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1417
+ "dev": true,
1418
+ "hasInstallScript": true,
1419
+ "license": "MIT",
1420
+ "optional": true,
1421
+ "os": [
1422
+ "darwin"
1423
+ ],
1424
+ "engines": {
1425
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1426
+ }
1427
+ },
1428
+ "node_modules/gensync": {
1429
+ "version": "1.0.0-beta.2",
1430
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1431
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1432
+ "dev": true,
1433
+ "license": "MIT",
1434
+ "engines": {
1435
+ "node": ">=6.9.0"
1436
+ }
1437
+ },
1438
+ "node_modules/js-tokens": {
1439
+ "version": "4.0.0",
1440
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1441
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1442
+ "license": "MIT"
1443
+ },
1444
+ "node_modules/jsesc": {
1445
+ "version": "3.1.0",
1446
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
1447
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
1448
+ "dev": true,
1449
+ "license": "MIT",
1450
+ "bin": {
1451
+ "jsesc": "bin/jsesc"
1452
+ },
1453
+ "engines": {
1454
+ "node": ">=6"
1455
+ }
1456
+ },
1457
+ "node_modules/json5": {
1458
+ "version": "2.2.3",
1459
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
1460
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
1461
+ "dev": true,
1462
+ "license": "MIT",
1463
+ "bin": {
1464
+ "json5": "lib/cli.js"
1465
+ },
1466
+ "engines": {
1467
+ "node": ">=6"
1468
+ }
1469
+ },
1470
+ "node_modules/loose-envify": {
1471
+ "version": "1.4.0",
1472
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
1473
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
1474
+ "license": "MIT",
1475
+ "dependencies": {
1476
+ "js-tokens": "^3.0.0 || ^4.0.0"
1477
+ },
1478
+ "bin": {
1479
+ "loose-envify": "cli.js"
1480
+ }
1481
+ },
1482
+ "node_modules/lru-cache": {
1483
+ "version": "5.1.1",
1484
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
1485
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
1486
+ "dev": true,
1487
+ "license": "ISC",
1488
+ "dependencies": {
1489
+ "yallist": "^3.0.2"
1490
+ }
1491
+ },
1492
+ "node_modules/ms": {
1493
+ "version": "2.1.3",
1494
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1495
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1496
+ "dev": true,
1497
+ "license": "MIT"
1498
+ },
1499
+ "node_modules/nanoid": {
1500
+ "version": "3.3.11",
1501
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
1502
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
1503
+ "dev": true,
1504
+ "funding": [
1505
+ {
1506
+ "type": "github",
1507
+ "url": "https://github.com/sponsors/ai"
1508
+ }
1509
+ ],
1510
+ "license": "MIT",
1511
+ "bin": {
1512
+ "nanoid": "bin/nanoid.cjs"
1513
+ },
1514
+ "engines": {
1515
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1516
+ }
1517
+ },
1518
+ "node_modules/node-releases": {
1519
+ "version": "2.0.27",
1520
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
1521
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
1522
+ "dev": true,
1523
+ "license": "MIT"
1524
+ },
1525
+ "node_modules/picocolors": {
1526
+ "version": "1.1.1",
1527
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1528
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1529
+ "dev": true,
1530
+ "license": "ISC"
1531
+ },
1532
+ "node_modules/postcss": {
1533
+ "version": "8.5.6",
1534
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
1535
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
1536
+ "dev": true,
1537
+ "funding": [
1538
+ {
1539
+ "type": "opencollective",
1540
+ "url": "https://opencollective.com/postcss/"
1541
+ },
1542
+ {
1543
+ "type": "tidelift",
1544
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1545
+ },
1546
+ {
1547
+ "type": "github",
1548
+ "url": "https://github.com/sponsors/ai"
1549
+ }
1550
+ ],
1551
+ "license": "MIT",
1552
+ "dependencies": {
1553
+ "nanoid": "^3.3.11",
1554
+ "picocolors": "^1.1.1",
1555
+ "source-map-js": "^1.2.1"
1556
+ },
1557
+ "engines": {
1558
+ "node": "^10 || ^12 || >=14"
1559
+ }
1560
+ },
1561
+ "node_modules/react": {
1562
+ "version": "18.3.1",
1563
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
1564
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
1565
+ "license": "MIT",
1566
+ "peer": true,
1567
+ "dependencies": {
1568
+ "loose-envify": "^1.1.0"
1569
+ },
1570
+ "engines": {
1571
+ "node": ">=0.10.0"
1572
+ }
1573
+ },
1574
+ "node_modules/react-dom": {
1575
+ "version": "18.3.1",
1576
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
1577
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
1578
+ "license": "MIT",
1579
+ "peer": true,
1580
+ "dependencies": {
1581
+ "loose-envify": "^1.1.0",
1582
+ "scheduler": "^0.23.2"
1583
+ },
1584
+ "peerDependencies": {
1585
+ "react": "^18.3.1"
1586
+ }
1587
+ },
1588
+ "node_modules/react-refresh": {
1589
+ "version": "0.17.0",
1590
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
1591
+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
1592
+ "dev": true,
1593
+ "license": "MIT",
1594
+ "engines": {
1595
+ "node": ">=0.10.0"
1596
+ }
1597
+ },
1598
+ "node_modules/react-router": {
1599
+ "version": "6.30.3",
1600
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
1601
+ "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
1602
+ "license": "MIT",
1603
+ "dependencies": {
1604
+ "@remix-run/router": "1.23.2"
1605
+ },
1606
+ "engines": {
1607
+ "node": ">=14.0.0"
1608
+ },
1609
+ "peerDependencies": {
1610
+ "react": ">=16.8"
1611
+ }
1612
+ },
1613
+ "node_modules/react-router-dom": {
1614
+ "version": "6.30.3",
1615
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
1616
+ "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
1617
+ "license": "MIT",
1618
+ "dependencies": {
1619
+ "@remix-run/router": "1.23.2",
1620
+ "react-router": "6.30.3"
1621
+ },
1622
+ "engines": {
1623
+ "node": ">=14.0.0"
1624
+ },
1625
+ "peerDependencies": {
1626
+ "react": ">=16.8",
1627
+ "react-dom": ">=16.8"
1628
+ }
1629
+ },
1630
+ "node_modules/rollup": {
1631
+ "version": "4.55.1",
1632
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
1633
+ "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
1634
+ "dev": true,
1635
+ "license": "MIT",
1636
+ "dependencies": {
1637
+ "@types/estree": "1.0.8"
1638
+ },
1639
+ "bin": {
1640
+ "rollup": "dist/bin/rollup"
1641
+ },
1642
+ "engines": {
1643
+ "node": ">=18.0.0",
1644
+ "npm": ">=8.0.0"
1645
+ },
1646
+ "optionalDependencies": {
1647
+ "@rollup/rollup-android-arm-eabi": "4.55.1",
1648
+ "@rollup/rollup-android-arm64": "4.55.1",
1649
+ "@rollup/rollup-darwin-arm64": "4.55.1",
1650
+ "@rollup/rollup-darwin-x64": "4.55.1",
1651
+ "@rollup/rollup-freebsd-arm64": "4.55.1",
1652
+ "@rollup/rollup-freebsd-x64": "4.55.1",
1653
+ "@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
1654
+ "@rollup/rollup-linux-arm-musleabihf": "4.55.1",
1655
+ "@rollup/rollup-linux-arm64-gnu": "4.55.1",
1656
+ "@rollup/rollup-linux-arm64-musl": "4.55.1",
1657
+ "@rollup/rollup-linux-loong64-gnu": "4.55.1",
1658
+ "@rollup/rollup-linux-loong64-musl": "4.55.1",
1659
+ "@rollup/rollup-linux-ppc64-gnu": "4.55.1",
1660
+ "@rollup/rollup-linux-ppc64-musl": "4.55.1",
1661
+ "@rollup/rollup-linux-riscv64-gnu": "4.55.1",
1662
+ "@rollup/rollup-linux-riscv64-musl": "4.55.1",
1663
+ "@rollup/rollup-linux-s390x-gnu": "4.55.1",
1664
+ "@rollup/rollup-linux-x64-gnu": "4.55.1",
1665
+ "@rollup/rollup-linux-x64-musl": "4.55.1",
1666
+ "@rollup/rollup-openbsd-x64": "4.55.1",
1667
+ "@rollup/rollup-openharmony-arm64": "4.55.1",
1668
+ "@rollup/rollup-win32-arm64-msvc": "4.55.1",
1669
+ "@rollup/rollup-win32-ia32-msvc": "4.55.1",
1670
+ "@rollup/rollup-win32-x64-gnu": "4.55.1",
1671
+ "@rollup/rollup-win32-x64-msvc": "4.55.1",
1672
+ "fsevents": "~2.3.2"
1673
+ }
1674
+ },
1675
+ "node_modules/scheduler": {
1676
+ "version": "0.23.2",
1677
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
1678
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
1679
+ "license": "MIT",
1680
+ "dependencies": {
1681
+ "loose-envify": "^1.1.0"
1682
+ }
1683
+ },
1684
+ "node_modules/semver": {
1685
+ "version": "6.3.1",
1686
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
1687
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
1688
+ "dev": true,
1689
+ "license": "ISC",
1690
+ "bin": {
1691
+ "semver": "bin/semver.js"
1692
+ }
1693
+ },
1694
+ "node_modules/source-map-js": {
1695
+ "version": "1.2.1",
1696
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1697
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1698
+ "dev": true,
1699
+ "license": "BSD-3-Clause",
1700
+ "engines": {
1701
+ "node": ">=0.10.0"
1702
+ }
1703
+ },
1704
+ "node_modules/typescript": {
1705
+ "version": "5.9.3",
1706
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
1707
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
1708
+ "dev": true,
1709
+ "license": "Apache-2.0",
1710
+ "bin": {
1711
+ "tsc": "bin/tsc",
1712
+ "tsserver": "bin/tsserver"
1713
+ },
1714
+ "engines": {
1715
+ "node": ">=14.17"
1716
+ }
1717
+ },
1718
+ "node_modules/undici-types": {
1719
+ "version": "7.16.0",
1720
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
1721
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
1722
+ "dev": true,
1723
+ "license": "MIT"
1724
+ },
1725
+ "node_modules/update-browserslist-db": {
1726
+ "version": "1.2.3",
1727
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
1728
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
1729
+ "dev": true,
1730
+ "funding": [
1731
+ {
1732
+ "type": "opencollective",
1733
+ "url": "https://opencollective.com/browserslist"
1734
+ },
1735
+ {
1736
+ "type": "tidelift",
1737
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1738
+ },
1739
+ {
1740
+ "type": "github",
1741
+ "url": "https://github.com/sponsors/ai"
1742
+ }
1743
+ ],
1744
+ "license": "MIT",
1745
+ "dependencies": {
1746
+ "escalade": "^3.2.0",
1747
+ "picocolors": "^1.1.1"
1748
+ },
1749
+ "bin": {
1750
+ "update-browserslist-db": "cli.js"
1751
+ },
1752
+ "peerDependencies": {
1753
+ "browserslist": ">= 4.21.0"
1754
+ }
1755
+ },
1756
+ "node_modules/vite": {
1757
+ "version": "5.4.21",
1758
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
1759
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
1760
+ "dev": true,
1761
+ "license": "MIT",
1762
+ "peer": true,
1763
+ "dependencies": {
1764
+ "esbuild": "^0.21.3",
1765
+ "postcss": "^8.4.43",
1766
+ "rollup": "^4.20.0"
1767
+ },
1768
+ "bin": {
1769
+ "vite": "bin/vite.js"
1770
+ },
1771
+ "engines": {
1772
+ "node": "^18.0.0 || >=20.0.0"
1773
+ },
1774
+ "funding": {
1775
+ "url": "https://github.com/vitejs/vite?sponsor=1"
1776
+ },
1777
+ "optionalDependencies": {
1778
+ "fsevents": "~2.3.3"
1779
+ },
1780
+ "peerDependencies": {
1781
+ "@types/node": "^18.0.0 || >=20.0.0",
1782
+ "less": "*",
1783
+ "lightningcss": "^1.21.0",
1784
+ "sass": "*",
1785
+ "sass-embedded": "*",
1786
+ "stylus": "*",
1787
+ "sugarss": "*",
1788
+ "terser": "^5.4.0"
1789
+ },
1790
+ "peerDependenciesMeta": {
1791
+ "@types/node": {
1792
+ "optional": true
1793
+ },
1794
+ "less": {
1795
+ "optional": true
1796
+ },
1797
+ "lightningcss": {
1798
+ "optional": true
1799
+ },
1800
+ "sass": {
1801
+ "optional": true
1802
+ },
1803
+ "sass-embedded": {
1804
+ "optional": true
1805
+ },
1806
+ "stylus": {
1807
+ "optional": true
1808
+ },
1809
+ "sugarss": {
1810
+ "optional": true
1811
+ },
1812
+ "terser": {
1813
+ "optional": true
1814
+ }
1815
+ }
1816
+ },
1817
+ "node_modules/ws": {
1818
+ "version": "8.19.0",
1819
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
1820
+ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
1821
+ "license": "MIT",
1822
+ "engines": {
1823
+ "node": ">=10.0.0"
1824
+ },
1825
+ "peerDependencies": {
1826
+ "bufferutil": "^4.0.1",
1827
+ "utf-8-validate": ">=5.0.2"
1828
+ },
1829
+ "peerDependenciesMeta": {
1830
+ "bufferutil": {
1831
+ "optional": true
1832
+ },
1833
+ "utf-8-validate": {
1834
+ "optional": true
1835
+ }
1836
+ }
1837
+ },
1838
+ "node_modules/yallist": {
1839
+ "version": "3.1.1",
1840
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
1841
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
1842
+ "dev": true,
1843
+ "license": "ISC"
1844
+ }
1845
+ }
1846
+ }
package.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "yuki",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "tsc && vite build",
8
+ "preview": "vite preview",
9
+ "start": "bun run dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.3.1",
13
+ "react-dom": "^18.3.1",
14
+ "ws": "^8.18.0",
15
+ "react-router-dom": "^6.26.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/react": "^18.3.3",
19
+ "@types/react-dom": "^18.3.0",
20
+ "@types/ws": "^8.5.12",
21
+ "@types/bun": "^1.3.5",
22
+ "@types/node": "^25.0.3",
23
+ "@vitejs/plugin-react": "^4.3.1",
24
+ "typescript": "^5.5.3",
25
+ "vite": "^5.4.2"
26
+ }
27
+ }
src/App.tsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { BrowserRouter, Route, Routes } from "react-router-dom";
2
+ import { NotFoundPage } from "./modules/error/NotFound";
3
+ import { HomePage } from "./modules/homepage/HomePage";
4
+ import { RegisterPage } from "./modules/register/RegisterPage";
5
+
6
+ export default function App() {
7
+ return (
8
+ <BrowserRouter>
9
+ <Routes>
10
+ <Route path="/" element={<HomePage />} />
11
+ <Route path="/register/:sessionId" element={<RegisterPage />} />
12
+ <Route path="*" element={<NotFoundPage />} />
13
+ </Routes>
14
+ </BrowserRouter>
15
+ )
16
+ }
src/index.css ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@300..700&display=swap');
2
+
3
+ * {
4
+ margin: 0;
5
+ padding: 0;
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ body {
10
+ font-family: "Comfortaa", sans-serif;
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ min-height: 100vh;
14
+ }
15
+
16
+ #root {
17
+ min-height: 100vh;
18
+ }
19
+
20
+ code {
21
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
22
+ monospace;
23
+ }
src/main.tsx ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import './index.css';
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ )
src/modules/error/NotFound.tsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import "./NotFoundPage.css";
2
+ import { Link } from "react-router-dom";
3
+
4
+ export function NotFoundPage() {
5
+ return (
6
+ <div className="notfound-container">
7
+ <div className="notfound-card">
8
+ <div className="notfound-icon">🔍</div>
9
+ <h1>404</h1>
10
+ <h2>Page Not Found</h2>
11
+ <p>The page you're looking for doesn't exist or has been moved.</p>
12
+ <Link to="/" className="home-button">
13
+ Go to Home
14
+ </Link>
15
+ </div>
16
+ </div>
17
+ )
18
+ }
src/modules/error/NotFoundPage.css ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .notfound-container {
2
+ min-height: 100vh;
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ padding: 20px;
7
+ }
8
+
9
+ .notfound-card {
10
+ border: 1px solid black;
11
+ box-shadow: 4px 4px 0 black;
12
+ border-radius: 5px;
13
+ padding: 10px 30px;
14
+ }
15
+
16
+ @keyframes bounceIn {
17
+ 0% {
18
+ opacity: 0;
19
+ transform: scale(0.3);
20
+ }
21
+ 50% {
22
+ transform: scale(1.05);
23
+ }
24
+ 100% {
25
+ opacity: 1;
26
+ transform: scale(1);
27
+ }
28
+ }
29
+
30
+ .notfound-icon {
31
+ font-size: 80px;
32
+ margin-bottom: 20px;
33
+ animation: float 3s ease-in-out infinite;
34
+ }
35
+
36
+ @keyframes float {
37
+ 0%, 100% {
38
+ transform: translateY(0px);
39
+ }
40
+ 50% {
41
+ transform: translateY(-20px);
42
+ }
43
+ }
44
+
45
+ .notfound-card h1 {
46
+ font-size: 72px;
47
+ color: #667eea;
48
+ margin-bottom: 10px;
49
+ font-weight: 700;
50
+ }
51
+
52
+ .notfound-card h2 {
53
+ font-size: 28px;
54
+ color: #333;
55
+ margin-bottom: 15px;
56
+ }
57
+
58
+ .notfound-card p {
59
+ color: #666;
60
+ font-size: 16px;
61
+ margin-bottom: 30px;
62
+ line-height: 1.6;
63
+ }
64
+
65
+ .home-button {
66
+ display: inline-block;
67
+ padding: 14px 32px;
68
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
69
+ color: white;
70
+ text-decoration: none;
71
+ border-radius: 10px;
72
+ font-size: 16px;
73
+ font-weight: 600;
74
+ transition: all 0.3s ease;
75
+ -webkit-tap-highlight-color: transparent;
76
+ }
77
+
78
+ .home-button:hover {
79
+ transform: translateY(-2px);
80
+ box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4);
81
+ }
82
+
83
+ .home-button:active {
84
+ transform: translateY(0);
85
+ }
86
+
87
+ @media (max-width: 600px) {
88
+ .notfound-card {
89
+ padding: 40px 20px;
90
+ }
91
+
92
+ .notfound-card h1 {
93
+ font-size: 56px;
94
+ }
95
+
96
+ .notfound-card h2 {
97
+ font-size: 24px;
98
+ }
99
+ }
src/modules/homepage/HomePage.css ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .homepage {
2
+ position: relative;
3
+ overflow: hidden;
4
+ min-height: 100vh;
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ background: #f5f5f5;
9
+ padding: 20px;
10
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
11
+ }
12
+
13
+ .homepage::before {
14
+ content: "";
15
+ position: absolute;
16
+ width: 500px;
17
+ height: 500px;
18
+ background: radial-gradient(
19
+ circle at top left,
20
+ #fdbb58,
21
+ #ff8fab,
22
+ transparent 70%
23
+ );
24
+ top: -150px;
25
+ left: -150px;
26
+ filter: blur(60px);
27
+ opacity: 0.6;
28
+ }
29
+
30
+ .homepage::after {
31
+ content: "";
32
+ position: absolute;
33
+ width: 400px;
34
+ height: 400px;
35
+ background: radial-gradient(
36
+ circle at bottom right,
37
+ #7dd3fc,
38
+ #c084fc,
39
+ transparent 70%
40
+ );
41
+ bottom: -120px;
42
+ right: -120px;
43
+ filter: blur(60px);
44
+ opacity: 0.6;
45
+ }
46
+
47
+ .card {
48
+ background: white;
49
+ border: 1px solid black;
50
+ box-shadow: 4px 4px 0 black;
51
+ border-radius: 5px;
52
+ padding: 40px;
53
+ max-width: 400px;
54
+ width: 100%;
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ gap: 20px;
59
+ position: relative;
60
+ z-index: 1;
61
+ }
62
+
63
+ .profile-section {
64
+ display: flex;
65
+ flex-direction: column;
66
+ align-items: center;
67
+ gap: 15px;
68
+ text-align: center;
69
+ }
70
+
71
+ .profile-image {
72
+ width: 120px;
73
+ height: 120px;
74
+ border-radius: 50%;
75
+ border: 2px solid black;
76
+ object-fit: cover;
77
+ }
78
+
79
+ .profile-name {
80
+ font-size: 24px;
81
+ font-weight: 700;
82
+ color: #333;
83
+ }
84
+
85
+ .profile-description {
86
+ font-size: 16px;
87
+ color: #666;
88
+ line-height: 1.5;
89
+ }
90
+
91
+ .version-badge {
92
+ background: #e8e8e8;
93
+ border: 1px solid black;
94
+ border-radius: 5px;
95
+ padding: 8px 16px;
96
+ font-size: 14px;
97
+ font-weight: 600;
98
+ }
99
+
100
+ .version-badge span {
101
+ color: #333;
102
+ }
103
+
104
+ .chat-button {
105
+ background: #fdbb58;
106
+ border-radius: 5px;
107
+ border: 1px solid black;
108
+ box-shadow: 4px 4px 0 black;
109
+ padding: 10px 30px;
110
+ cursor: pointer;
111
+ font-weight: 600;
112
+ font-size: 16px;
113
+ transition: all 0.1s ease;
114
+ -webkit-tap-highlight-color: transparent;
115
+ width: 100%;
116
+ max-width: 250px;
117
+ }
118
+
119
+ .chat-button:hover {
120
+ transform: translateY(-2px);
121
+ }
122
+
123
+ .chat-button:active {
124
+ box-shadow: 0px 0px 0 black;
125
+ border: 2px solid black;
126
+ transform: translateY(2px);
127
+ }
128
+
129
+ @media (max-width: 480px) {
130
+ .card {
131
+ padding: 30px 20px;
132
+ }
133
+
134
+ .profile-image {
135
+ width: 100px;
136
+ height: 100px;
137
+ }
138
+
139
+ .profile-name {
140
+ font-size: 20px;
141
+ }
142
+
143
+ .profile-description {
144
+ font-size: 14px;
145
+ }
146
+ }
src/modules/homepage/HomePage.tsx ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState, useEffect } from "react";
2
+ import "./HomePage.css";
3
+
4
+ export function HomePage() {
5
+ const [profileData, setProfileData]: [any, any] = useState(null);
6
+ const [version, setVersion] = useState(null);
7
+ const [loading, setLoading] = useState(true);
8
+
9
+ useEffect(() => {
10
+ const fetchData = async () => {
11
+ try {
12
+ const username = "OhMyDitzzy";
13
+ const repo = "Yuki";
14
+
15
+ const profileRes = await fetch(`https://api.github.com/users/${username}`);
16
+ const profileJson = await profileRes.json();
17
+ setProfileData(profileJson);
18
+
19
+ const packageRes = await fetch(
20
+ `https://raw.githubusercontent.com/${username}/${repo}/main/package.json`
21
+ );
22
+ const packageJson = await packageRes.json();
23
+ setVersion(packageJson.version);
24
+
25
+ setLoading(false);
26
+ } catch (error) {
27
+ console.error("Error fetching data:", error);
28
+ setLoading(false);
29
+ }
30
+ };
31
+
32
+ fetchData();
33
+ }, []);
34
+
35
+ if (loading) {
36
+ return (
37
+ <div className="homepage">
38
+ <div>Loading...</div>
39
+ </div>
40
+ );
41
+ }
42
+
43
+ return (
44
+ <div className="homepage">
45
+ <div className="card">
46
+ <div className="profile-section">
47
+ <img
48
+ src={profileData?.avatar_url || "/profile.jpg"}
49
+ alt="Profile"
50
+ className="profile-image"
51
+ />
52
+ <h1 className="profile-name">{profileData?.name || "Your Name"}</h1>
53
+ <p className="profile-description">
54
+ {profileData?.bio || "No description available"}
55
+ </p>
56
+ </div>
57
+
58
+ {version && (
59
+ <div className="version-badge">
60
+ <span>v{version}</span>
61
+ </div>
62
+ )}
63
+
64
+ <button className="chat-button" onClick={() => window.location.href = "https://chat.whatsapp.com/JnQ0MStkXq05MR4gDgAcTJ"}>
65
+ Chat with bot
66
+ </button>
67
+ </div>
68
+ </div>
69
+ );
70
+ }
src/modules/register/RegisterPage.css ADDED
@@ -0,0 +1,486 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .register-page {
2
+ position: relative;
3
+ overflow: hidden;
4
+ min-height: 100vh;
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ background: #f5f5f5;
9
+ padding: 20px;
10
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
11
+ }
12
+
13
+ .register-page::before {
14
+ content: "";
15
+ position: absolute;
16
+ width: 500px;
17
+ height: 500px;
18
+ background: radial-gradient(
19
+ circle at top left,
20
+ #fdbb58,
21
+ #ff8fab,
22
+ transparent 70%
23
+ );
24
+ top: -150px;
25
+ left: -150px;
26
+ filter: blur(60px);
27
+ opacity: 0.6;
28
+ animation: float 6s ease-in-out infinite;
29
+ }
30
+
31
+ .register-page::after {
32
+ content: "";
33
+ position: absolute;
34
+ width: 400px;
35
+ height: 400px;
36
+ background: radial-gradient(
37
+ circle at bottom right,
38
+ #7dd3fc,
39
+ #c084fc,
40
+ transparent 70%
41
+ );
42
+ bottom: -120px;
43
+ right: -120px;
44
+ filter: blur(60px);
45
+ opacity: 0.6;
46
+ animation: float 8s ease-in-out infinite;
47
+ }
48
+
49
+ @keyframes float {
50
+ 0%, 100% {
51
+ transform: translateY(0px);
52
+ }
53
+ 50% {
54
+ transform: translateY(-20px);
55
+ }
56
+ }
57
+
58
+ .register-card {
59
+ background: white;
60
+ border: 2px solid black;
61
+ box-shadow: 6px 6px 0 black;
62
+ border-radius: 8px;
63
+ padding: 40px;
64
+ max-width: 500px;
65
+ width: 100%;
66
+ position: relative;
67
+ z-index: 1;
68
+ animation: slideUp 0.5s ease-out;
69
+ }
70
+
71
+ @keyframes slideUp {
72
+ from {
73
+ opacity: 0;
74
+ transform: translateY(30px);
75
+ }
76
+ to {
77
+ opacity: 1;
78
+ transform: translateY(0);
79
+ }
80
+ }
81
+
82
+ .register-header {
83
+ text-align: center;
84
+ margin-bottom: 30px;
85
+ }
86
+
87
+ .register-header h1 {
88
+ font-size: 28px;
89
+ font-weight: 700;
90
+ color: #333;
91
+ margin-bottom: 10px;
92
+ }
93
+
94
+ .register-header p {
95
+ font-size: 16px;
96
+ color: #666;
97
+ margin-bottom: 15px;
98
+ }
99
+
100
+ .connection-status {
101
+ display: inline-flex;
102
+ align-items: center;
103
+ gap: 8px;
104
+ padding: 6px 12px;
105
+ border-radius: 20px;
106
+ font-size: 12px;
107
+ font-weight: 600;
108
+ }
109
+
110
+ .connection-status.offline {
111
+ background: #fee;
112
+ color: #c33;
113
+ border: 1px solid #fcc;
114
+ }
115
+
116
+ .status-dot {
117
+ width: 8px;
118
+ height: 8px;
119
+ border-radius: 50%;
120
+ background: currentColor;
121
+ animation: pulse 1.5s ease-in-out infinite;
122
+ }
123
+
124
+ @keyframes pulse {
125
+ 0%, 100% {
126
+ opacity: 1;
127
+ }
128
+ 50% {
129
+ opacity: 0.4;
130
+ }
131
+ }
132
+
133
+ .register-form {
134
+ display: flex;
135
+ flex-direction: column;
136
+ gap: 20px;
137
+ }
138
+
139
+ .form-group {
140
+ display: flex;
141
+ flex-direction: column;
142
+ gap: 8px;
143
+ }
144
+
145
+ .form-group label {
146
+ display: flex;
147
+ align-items: center;
148
+ gap: 8px;
149
+ font-weight: 600;
150
+ font-size: 14px;
151
+ color: #333;
152
+ }
153
+
154
+ .label-icon {
155
+ font-size: 18px;
156
+ }
157
+
158
+ .form-group input {
159
+ padding: 12px 16px;
160
+ border: 2px solid #ddd;
161
+ border-radius: 6px;
162
+ font-size: 16px;
163
+ transition: all 0.2s ease;
164
+ font-family: inherit;
165
+ }
166
+
167
+ .form-group input:focus {
168
+ outline: none;
169
+ border-color: #fdbb58;
170
+ box-shadow: 0 0 0 3px rgba(253, 187, 88, 0.1);
171
+ }
172
+
173
+ .form-group input.error {
174
+ border-color: #f44336;
175
+ }
176
+
177
+ .form-group input:disabled {
178
+ background: #f5f5f5;
179
+ cursor: not-allowed;
180
+ }
181
+
182
+ .error-text {
183
+ color: #f44336;
184
+ font-size: 13px;
185
+ font-weight: 500;
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 4px;
189
+ }
190
+
191
+ .error-text::before {
192
+ content: "⚠️";
193
+ font-size: 12px;
194
+ }
195
+
196
+ .password-section {
197
+ border: 2px solid #e8e8e8;
198
+ border-radius: 8px;
199
+ padding: 20px;
200
+ background: #fafafa;
201
+ }
202
+
203
+ .section-header {
204
+ display: flex;
205
+ justify-content: space-between;
206
+ align-items: center;
207
+ margin-bottom: 15px;
208
+ }
209
+
210
+ .section-header h3 {
211
+ font-size: 16px;
212
+ font-weight: 700;
213
+ color: #333;
214
+ margin: 0;
215
+ }
216
+
217
+ .checkbox-label {
218
+ display: flex;
219
+ align-items: center;
220
+ gap: 8px;
221
+ cursor: pointer;
222
+ font-size: 14px;
223
+ color: #666;
224
+ }
225
+
226
+ .checkbox-label input[type="checkbox"] {
227
+ width: 18px;
228
+ height: 18px;
229
+ cursor: pointer;
230
+ }
231
+
232
+ .bonus-badge {
233
+ display: flex;
234
+ align-items: center;
235
+ gap: 8px;
236
+ background: linear-gradient(135deg, #fdbb58, #ff8fab);
237
+ color: white;
238
+ padding: 12px 16px;
239
+ border-radius: 8px;
240
+ font-weight: 600;
241
+ font-size: 14px;
242
+ margin-bottom: 15px;
243
+ border: 2px solid rgba(0, 0, 0, 0.1);
244
+ }
245
+
246
+ .badge-icon {
247
+ font-size: 20px;
248
+ }
249
+
250
+ .rewards-list {
251
+ display: grid;
252
+ grid-template-columns: repeat(2, 1fr);
253
+ gap: 10px;
254
+ margin-bottom: 15px;
255
+ }
256
+
257
+ .reward-item {
258
+ background: white;
259
+ padding: 10px;
260
+ border-radius: 6px;
261
+ border: 1px solid #ddd;
262
+ font-size: 13px;
263
+ font-weight: 600;
264
+ text-align: center;
265
+ color: #333;
266
+ }
267
+
268
+ .alert {
269
+ display: flex;
270
+ align-items: center;
271
+ gap: 10px;
272
+ padding: 12px 16px;
273
+ border-radius: 6px;
274
+ font-size: 14px;
275
+ font-weight: 500;
276
+ }
277
+
278
+ .alert-error {
279
+ background: #fee;
280
+ color: #c33;
281
+ border: 1px solid #fcc;
282
+ }
283
+
284
+ .alert-icon {
285
+ font-size: 18px;
286
+ }
287
+
288
+ .submit-button {
289
+ background: #fdbb58;
290
+ color: #000;
291
+ border: 2px solid black;
292
+ box-shadow: 4px 4px 0 black;
293
+ border-radius: 6px;
294
+ padding: 14px 30px;
295
+ font-size: 16px;
296
+ font-weight: 700;
297
+ cursor: pointer;
298
+ transition: all 0.1s ease;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ gap: 10px;
303
+ margin-top: 10px;
304
+ }
305
+
306
+ .submit-button:hover:not(:disabled) {
307
+ transform: translateY(-2px);
308
+ box-shadow: 6px 6px 0 black;
309
+ }
310
+
311
+ .submit-button:active:not(:disabled) {
312
+ transform: translateY(2px);
313
+ box-shadow: 0px 0px 0 black;
314
+ }
315
+
316
+ .submit-button:disabled {
317
+ opacity: 0.6;
318
+ cursor: not-allowed;
319
+ transform: none !important;
320
+ }
321
+
322
+ .button-spinner {
323
+ width: 16px;
324
+ height: 16px;
325
+ border: 2px solid rgba(0, 0, 0, 0.2);
326
+ border-top-color: #000;
327
+ border-radius: 50%;
328
+ animation: spin 0.6s linear infinite;
329
+ }
330
+
331
+ @keyframes spin {
332
+ to {
333
+ transform: rotate(360deg);
334
+ }
335
+ }
336
+
337
+ .form-footer {
338
+ text-align: center;
339
+ font-size: 13px;
340
+ color: #666;
341
+ margin-top: 10px;
342
+ }
343
+
344
+ /* Loading state */
345
+ .loading-spinner {
346
+ display: flex;
347
+ flex-direction: column;
348
+ align-items: center;
349
+ gap: 20px;
350
+ padding: 40px;
351
+ }
352
+
353
+ .spinner {
354
+ width: 50px;
355
+ height: 50px;
356
+ border: 4px solid #e8e8e8;
357
+ border-top-color: #fdbb58;
358
+ border-radius: 50%;
359
+ animation: spin 0.8s linear infinite;
360
+ }
361
+
362
+ .loading-spinner p {
363
+ font-size: 16px;
364
+ color: #666;
365
+ font-weight: 500;
366
+ }
367
+
368
+ .error-card,
369
+ .success-card {
370
+ text-align: center;
371
+ }
372
+
373
+ .error-icon,
374
+ .success-icon {
375
+ font-size: 60px;
376
+ margin-bottom: 20px;
377
+ animation: bounce 0.5s ease-out;
378
+ }
379
+
380
+ @keyframes bounce {
381
+ 0%, 100% {
382
+ transform: scale(1);
383
+ }
384
+ 50% {
385
+ transform: scale(1.2);
386
+ }
387
+ }
388
+
389
+ .error-card h2,
390
+ .success-card h2 {
391
+ font-size: 24px;
392
+ font-weight: 700;
393
+ color: #333;
394
+ margin-bottom: 10px;
395
+ }
396
+
397
+ .error-card p,
398
+ .success-card p {
399
+ font-size: 16px;
400
+ color: #666;
401
+ margin-bottom: 20px;
402
+ line-height: 1.5;
403
+ }
404
+
405
+ .success-subtitle {
406
+ font-size: 14px !important;
407
+ color: #999 !important;
408
+ }
409
+
410
+ .back-button {
411
+ background: #333;
412
+ color: white;
413
+ border: 2px solid black;
414
+ box-shadow: 4px 4px 0 black;
415
+ border-radius: 6px;
416
+ padding: 12px 30px;
417
+ font-size: 16px;
418
+ font-weight: 600;
419
+ cursor: pointer;
420
+ transition: all 0.1s ease;
421
+ }
422
+
423
+ .back-button:hover {
424
+ transform: translateY(-2px);
425
+ box-shadow: 6px 6px 0 black;
426
+ }
427
+
428
+ .back-button:active {
429
+ transform: translateY(2px);
430
+ box-shadow: 0px 0px 0 black;
431
+ }
432
+
433
+ .success-animation {
434
+ position: absolute;
435
+ top: 0;
436
+ left: 0;
437
+ right: 0;
438
+ bottom: 0;
439
+ pointer-events: none;
440
+ overflow: hidden;
441
+ }
442
+
443
+ .confetti {
444
+ position: absolute;
445
+ width: 10px;
446
+ height: 10px;
447
+ background: #fdbb58;
448
+ animation: confetti-fall 3s ease-out forwards;
449
+ }
450
+
451
+ @keyframes confetti-fall {
452
+ to {
453
+ transform: translateY(100vh) rotate(360deg);
454
+ opacity: 0;
455
+ }
456
+ }
457
+
458
+ @media (max-width: 600px) {
459
+ .register-card {
460
+ padding: 30px 20px;
461
+ }
462
+
463
+ .register-header h1 {
464
+ font-size: 24px;
465
+ }
466
+
467
+ .rewards-list {
468
+ grid-template-columns: 1fr;
469
+ }
470
+
471
+ .section-header {
472
+ flex-direction: column;
473
+ align-items: flex-start;
474
+ gap: 10px;
475
+ }
476
+ }
477
+
478
+ input[type="number"]::-webkit-inner-spin-button,
479
+ input[type="number"]::-webkit-outer-spin-button {
480
+ -webkit-appearance: none;
481
+ margin: 0;
482
+ }
483
+
484
+ input[type="number"] {
485
+ -moz-appearance: textfield;
486
+ }
src/modules/register/RegisterPage.tsx ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState, useEffect, useRef } from "react";
2
+ import { useParams, useNavigate } from "react-router-dom";
3
+ import "./RegisterPage.css";
4
+
5
+ interface RegistrationData {
6
+ username: string;
7
+ age: string;
8
+ password: string;
9
+ confirmPassword: string;
10
+ }
11
+
12
+ export function RegisterPage() {
13
+ const { sessionId } = useParams<{ sessionId: string }>();
14
+ const navigate = useNavigate();
15
+
16
+ const [ws, setWs] = useState<WebSocket | null>(null);
17
+ const [connected, setConnected] = useState(false);
18
+ const [sessionValid, setSessionValid] = useState<boolean | null>(null);
19
+ const [loading, setLoading] = useState(true);
20
+ const [submitting, setSubmitting] = useState(false);
21
+ const [skipPassword, setSkipPassword] = useState(false);
22
+
23
+ const [formData, setFormData] = useState<RegistrationData>({
24
+ username: "",
25
+ age: "",
26
+ password: "",
27
+ confirmPassword: "",
28
+ });
29
+
30
+ const [errors, setErrors] = useState<Partial<RegistrationData>>({});
31
+ const [successMessage, setSuccessMessage] = useState("");
32
+ const [errorMessage, setErrorMessage] = useState("");
33
+
34
+ const wsRef = useRef<WebSocket | null>(null);
35
+
36
+ useEffect(() => {
37
+ if (!sessionId) {
38
+ setSessionValid(false);
39
+ setLoading(false);
40
+ return;
41
+ }
42
+
43
+ const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
44
+ const wsUrl = `${protocol}//${window.location.host}/ws`;
45
+ const websocket = new WebSocket(wsUrl);
46
+
47
+ wsRef.current = websocket;
48
+
49
+ websocket.onopen = () => {
50
+ console.log("[WebSocket] Connected");
51
+ setConnected(true);
52
+
53
+ websocket.send(JSON.stringify({
54
+ type: "user_connect",
55
+ sessionId: sessionId,
56
+ }));
57
+ };
58
+
59
+ websocket.onmessage = (event) => {
60
+ try {
61
+ const message = JSON.parse(event.data);
62
+ handleWebSocketMessage(message);
63
+ } catch (error) {
64
+ console.error("[WebSocket] Error parsing message:", error);
65
+ }
66
+ };
67
+
68
+ websocket.onerror = (error) => {
69
+ console.error("[WebSocket] Error:", error);
70
+ setErrorMessage("Connection error. Please try again.");
71
+ setLoading(false);
72
+ };
73
+
74
+ websocket.onclose = () => {
75
+ console.log("[WebSocket] Disconnected");
76
+ setConnected(false);
77
+ };
78
+
79
+ setWs(websocket);
80
+
81
+ return () => {
82
+ websocket.close();
83
+ };
84
+ }, [sessionId]);
85
+
86
+ const handleWebSocketMessage = (message: any) => {
87
+ switch (message.type) {
88
+ case "connected":
89
+ console.log("[WebSocket]", message.message);
90
+ break;
91
+
92
+ case "session_valid":
93
+ setSessionValid(true);
94
+ setLoading(false);
95
+ break;
96
+
97
+ case "session_invalid":
98
+ setSessionValid(false);
99
+ setLoading(false);
100
+ setErrorMessage(message.message || "Session not found or expired");
101
+ break;
102
+
103
+ case "registration_result":
104
+ setSubmitting(false);
105
+ if (message.success) {
106
+ setSuccessMessage(message.message);
107
+ setErrorMessage("");
108
+ setTimeout(() => {
109
+ window.close();
110
+ }, 3000);
111
+ } else {
112
+ setErrorMessage(message.message);
113
+ setSuccessMessage("");
114
+ }
115
+ break;
116
+ }
117
+ };
118
+
119
+ const validateForm = (): boolean => {
120
+ const newErrors: Partial<RegistrationData> = {};
121
+
122
+ if (!formData.username.trim()) {
123
+ newErrors.username = "Username is required";
124
+ } else if (formData.username.trim().length < 3) {
125
+ newErrors.username = "Username must be at least 3 characters";
126
+ }
127
+
128
+ const ageNum = parseInt(formData.age);
129
+ if (!formData.age) {
130
+ newErrors.age = "Age is required";
131
+ } else if (isNaN(ageNum) || ageNum < 13 || ageNum > 100) {
132
+ newErrors.age = "Age must be between 13 and 100";
133
+ }
134
+
135
+ if (!skipPassword) {
136
+ if (!formData.password) {
137
+ newErrors.password = "Password is required";
138
+ } else if (formData.password.length < 6 || formData.password.length > 20) {
139
+ newErrors.password = "Password must be 6-20 characters";
140
+ }
141
+
142
+ if (!formData.confirmPassword) {
143
+ newErrors.confirmPassword = "Please confirm your password";
144
+ } else if (formData.password !== formData.confirmPassword) {
145
+ newErrors.confirmPassword = "Passwords do not match";
146
+ }
147
+ }
148
+
149
+ setErrors(newErrors);
150
+ return Object.keys(newErrors).length === 0;
151
+ };
152
+
153
+ const handleSubmit = (e: React.FormEvent) => {
154
+ e.preventDefault();
155
+
156
+ if (!validateForm()) return;
157
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
158
+ setErrorMessage("Connection lost. Please refresh the page.");
159
+ return;
160
+ }
161
+
162
+ setSubmitting(true);
163
+ setErrorMessage("");
164
+ setSuccessMessage("");
165
+
166
+ const submitData = {
167
+ username: formData.username.trim(),
168
+ age: parseInt(formData.age),
169
+ password: skipPassword ? "" : formData.password,
170
+ confirmPassword: skipPassword ? "" : formData.confirmPassword,
171
+ };
172
+
173
+ ws.send(JSON.stringify({
174
+ type: "registration_submit",
175
+ sessionId: sessionId,
176
+ data: submitData,
177
+ }));
178
+ };
179
+
180
+ const handleInputChange = (field: keyof RegistrationData, value: string) => {
181
+ setFormData(prev => ({ ...prev, [field]: value }));
182
+ if (errors[field]) {
183
+ setErrors(prev => ({ ...prev, [field]: "" }));
184
+ }
185
+ };
186
+
187
+ if (loading) {
188
+ return (
189
+ <div className="register-page">
190
+ <div className="register-card">
191
+ <div className="loading-spinner">
192
+ <div className="spinner"></div>
193
+ <p>Validating session...</p>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ );
198
+ }
199
+
200
+ if (sessionValid === false) {
201
+ return (
202
+ <div className="register-page">
203
+ <div className="register-card error-card">
204
+ <div className="error-icon">❌</div>
205
+ <h2>Invalid Session</h2>
206
+ <p>{errorMessage || "This registration link is invalid or has expired."}</p>
207
+ <button
208
+ className="back-button"
209
+ onClick={() => navigate("/")}
210
+ >
211
+ Go to Homepage
212
+ </button>
213
+ </div>
214
+ </div>
215
+ );
216
+ }
217
+
218
+ if (successMessage) {
219
+ return (
220
+ <div className="register-page">
221
+ <div className="register-card success-card">
222
+ <div className="success-icon">✅</div>
223
+ <h2>Registration Successful!</h2>
224
+ <p>{successMessage}</p>
225
+ <p className="success-subtitle">Please verify in WhatsApp to complete registration.</p>
226
+ <div className="success-animation">
227
+ <div className="confetti"></div>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ );
232
+ }
233
+
234
+ return (
235
+ <div className="register-page">
236
+ <div className="register-card">
237
+ <div className="register-header">
238
+ <h1>🎉 Account Registration</h1>
239
+ <p>Join Yuki Botz and unlock amazing features!</p>
240
+ {!connected && (
241
+ <div className="connection-status offline">
242
+ <span className="status-dot"></span>
243
+ Reconnecting...
244
+ </div>
245
+ )}
246
+ </div>
247
+
248
+ <form onSubmit={handleSubmit} className="register-form">
249
+ <div className="form-group">
250
+ <label htmlFor="username">
251
+ <span className="label-icon">👤</span>
252
+ Username
253
+ </label>
254
+ <input
255
+ type="text"
256
+ id="username"
257
+ value={formData.username}
258
+ onChange={(e) => handleInputChange("username", e.target.value)}
259
+ placeholder="Enter your username"
260
+ className={errors.username ? "error" : ""}
261
+ disabled={submitting}
262
+ />
263
+ {errors.username && <span className="error-text">{errors.username}</span>}
264
+ </div>
265
+
266
+ <div className="form-group">
267
+ <label htmlFor="age">
268
+ <span className="label-icon">🎂</span>
269
+ Age
270
+ </label>
271
+ <input
272
+ type="number"
273
+ id="age"
274
+ value={formData.age}
275
+ onChange={(e) => handleInputChange("age", e.target.value)}
276
+ placeholder="Enter your age"
277
+ className={errors.age ? "error" : ""}
278
+ disabled={submitting}
279
+ min="13"
280
+ max="100"
281
+ />
282
+ {errors.age && <span className="error-text">{errors.age}</span>}
283
+ </div>
284
+
285
+ <div className="password-section">
286
+ <div className="section-header">
287
+ <h3>🔑 Password (Optional)</h3>
288
+ <label className="checkbox-label">
289
+ <input
290
+ type="checkbox"
291
+ checked={skipPassword}
292
+ onChange={(e) => setSkipPassword(e.target.checked)}
293
+ disabled={submitting}
294
+ />
295
+ <span>Skip password</span>
296
+ </label>
297
+ </div>
298
+
299
+ {!skipPassword && (
300
+ <>
301
+ <div className="bonus-badge">
302
+ <span className="badge-icon">🎁</span>
303
+ <span>Set password & get bonus rewards!</span>
304
+ </div>
305
+
306
+ <div className="rewards-list">
307
+ <div className="reward-item">💎 +100 Limit</div>
308
+ <div className="reward-item">🪙 +10,000 Money</div>
309
+ <div className="reward-item">⭐ +50 EXP</div>
310
+ <div className="reward-item">🎮 RPG Access</div>
311
+ </div>
312
+
313
+ <div className="form-group">
314
+ <label htmlFor="password">Password</label>
315
+ <input
316
+ type="password"
317
+ id="password"
318
+ value={formData.password}
319
+ onChange={(e) => handleInputChange("password", e.target.value)}
320
+ placeholder="6-20 characters"
321
+ className={errors.password ? "error" : ""}
322
+ disabled={submitting}
323
+ />
324
+ {errors.password && <span className="error-text">{errors.password}</span>}
325
+ </div>
326
+
327
+ <div className="form-group">
328
+ <label htmlFor="confirmPassword">Confirm Password</label>
329
+ <input
330
+ type="password"
331
+ id="confirmPassword"
332
+ value={formData.confirmPassword}
333
+ onChange={(e) => handleInputChange("confirmPassword", e.target.value)}
334
+ placeholder="Re-enter password"
335
+ className={errors.confirmPassword ? "error" : ""}
336
+ disabled={submitting}
337
+ />
338
+ {errors.confirmPassword && <span className="error-text">{errors.confirmPassword}</span>}
339
+ </div>
340
+ </>
341
+ )}
342
+ </div>
343
+
344
+ {errorMessage && (
345
+ <div className="alert alert-error">
346
+ <span className="alert-icon">⚠️</span>
347
+ {errorMessage}
348
+ </div>
349
+ )}
350
+
351
+ <button
352
+ type="submit"
353
+ className="submit-button"
354
+ disabled={submitting || !connected}
355
+ >
356
+ {submitting ? (
357
+ <>
358
+ <span className="button-spinner"></span>
359
+ Processing...
360
+ </>
361
+ ) : (
362
+ <>
363
+ <span>🚀</span>
364
+ Complete Registration
365
+ </>
366
+ )}
367
+ </button>
368
+
369
+ <p className="form-footer">
370
+ After submitting, verify in WhatsApp to activate your account.
371
+ </p>
372
+ </form>
373
+ </div>
374
+ </div>
375
+ );
376
+ }
src/server/index.ts ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { serve } from "bun";
2
+ import { handleWebSocketConnection } from "./websocket";
3
+ import { router } from "./router";
4
+
5
+ const PORT = process.env.PORT || 7860;
6
+
7
+ export const server = serve({
8
+ port: PORT,
9
+ async fetch(req, server) {
10
+ const url = new URL(req.url);
11
+
12
+ if (url.pathname === "/ws") {
13
+ const upgraded = server.upgrade(req);
14
+ if (!upgraded) {
15
+ return new Response("WebSocket upgrade failed", { status: 400 });
16
+ }
17
+ return undefined;
18
+ }
19
+
20
+ return await router(req);
21
+ },
22
+ websocket: {
23
+ open(ws) {
24
+ console.log("[WebSocket] Client connected");
25
+ handleWebSocketConnection(ws);
26
+ },
27
+ message(ws: any, message) {
28
+ try {
29
+ const data = JSON.parse(message.toString());
30
+ ws.data?.handleMessage?.(data);
31
+ } catch (error) {
32
+ console.error("[WebSocket] Error parsing message:", error);
33
+ }
34
+ },
35
+ close(ws: any) {
36
+ console.log("[WebSocket] Client disconnected");
37
+ ws.data?.cleanup?.();
38
+ },
39
+ },
40
+ });
41
+
42
+ console.log(`Server running on http://localhost:${PORT}`);
43
+ console.log(`WebSocket available at ws://localhost:${PORT}/ws`);
src/server/router.ts ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { join } from "path";
2
+
3
+ // Serve static files from dist/public
4
+ const publicDir = join(process.cwd(), "dist", "public");
5
+
6
+ export async function router(req: Request): Promise<Response> {
7
+ const url = new URL(req.url);
8
+ const pathname = url.pathname;
9
+
10
+ if (pathname === "/health") {
11
+ return new Response(JSON.stringify({ status: "ok" }), {
12
+ headers: { "Content-Type": "application/json" },
13
+ });
14
+ }
15
+
16
+ if (pathname.startsWith("/api/")) {
17
+ return handleApiRequest(pathname);
18
+ }
19
+
20
+ return serveStatic(pathname);
21
+ }
22
+
23
+ async function handleApiRequest(pathname: string): Promise<Response> {
24
+ if (pathname.startsWith("/api/session/")) {
25
+ const sessionId = pathname.split("/").pop();
26
+ // TODO: add session validation logic if needed
27
+ return new Response(JSON.stringify({ sessionId, valid: true }), {
28
+ headers: { "Content-Type": "application/json" },
29
+ });
30
+ }
31
+
32
+ return new Response(JSON.stringify({ error: "Not found" }), {
33
+ status: 404,
34
+ headers: { "Content-Type": "application/json" },
35
+ });
36
+ }
37
+
38
+ function serveStatic(pathname: string): Response {
39
+ try {
40
+ let filePath = pathname === "/" ? "/index.html" : pathname;
41
+
42
+ const fullPath = join(publicDir, filePath);
43
+ const file = Bun.file(fullPath);
44
+
45
+ return new Response(file, {
46
+ headers: {
47
+ "Content-Type": getContentType(filePath),
48
+ },
49
+ });
50
+ } catch (error) {
51
+ // If file not found, serve index.html for SPA routing
52
+ try {
53
+ const indexPath = join(publicDir, "index.html");
54
+ const file = Bun.file(indexPath);
55
+ return new Response(file, {
56
+ headers: {
57
+ "Content-Type": "text/html",
58
+ },
59
+ });
60
+ } catch {
61
+ return new Response("Not found", { status: 404 });
62
+ }
63
+ }
64
+ }
65
+
66
+ function getContentType(pathname: string): string {
67
+ const ext = pathname.split(".").pop()?.toLowerCase();
68
+ const contentTypes: Record<string, string> = {
69
+ html: "text/html",
70
+ css: "text/css",
71
+ js: "application/javascript",
72
+ json: "application/json",
73
+ png: "image/png",
74
+ jpg: "image/jpeg",
75
+ jpeg: "image/jpeg",
76
+ gif: "image/gif",
77
+ svg: "image/svg+xml",
78
+ ico: "image/x-icon",
79
+ };
80
+ return contentTypes[ext || ""] || "application/octet-stream";
81
+ }
src/server/websocket.ts ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { ServerWebSocket } from "bun";
2
+
3
+ interface Session {
4
+ sessionId: string;
5
+ sender: string;
6
+ createdAt: number;
7
+ ws?: ServerWebSocket;
8
+ }
9
+
10
+ const sessions = new Map<string, Session>();
11
+
12
+ const botConnections = new Set<ServerWebSocket>();
13
+
14
+ export function handleWebSocketConnection(ws: ServerWebSocket) {
15
+ // @ts-ignore
16
+ ws.data = {
17
+ handleMessage: (message: any) => handleMessage(ws, message),
18
+ cleanup: () => cleanup(ws),
19
+ };
20
+
21
+ ws.send(JSON.stringify({
22
+ type: 'connected',
23
+ message: 'Connected to registration server'
24
+ }));
25
+ }
26
+
27
+ function handleMessage(ws: ServerWebSocket, message: any) {
28
+ const { type, sessionId } = message;
29
+
30
+ switch (type) {
31
+ case 'bot_connect':
32
+ botConnections.add(ws);
33
+ console.log('[WebSocket] Bot connected, total bots:', botConnections.size);
34
+ break;
35
+
36
+ case 'create_session':
37
+ sessions.set(sessionId, {
38
+ sessionId,
39
+ sender: message.sender,
40
+ createdAt: Date.now(),
41
+ });
42
+ console.log('[WebSocket] Session created:', sessionId);
43
+ break;
44
+
45
+ case 'user_connect':
46
+ const session = sessions.get(sessionId);
47
+ if (session) {
48
+ session.ws = ws;
49
+ ws.send(JSON.stringify({
50
+ type: 'session_valid',
51
+ sessionId
52
+ }));
53
+ } else {
54
+ ws.send(JSON.stringify({
55
+ type: 'session_invalid',
56
+ message: 'Session not found or expired'
57
+ }));
58
+ }
59
+ break;
60
+
61
+ case 'registration_submit':
62
+ handleRegistrationSubmit(sessionId, message.data);
63
+ break;
64
+
65
+ default:
66
+ console.log('[WebSocket] Unknown message type:', type);
67
+ }
68
+ }
69
+
70
+ function handleRegistrationSubmit(sessionId: string, data: any) {
71
+ const session = sessions.get(sessionId);
72
+ if (!session) {
73
+ return;
74
+ }
75
+
76
+ const { username, age, password, confirmPassword } = data;
77
+ let success = true;
78
+ let errorMessage = '';
79
+
80
+ if (!username || username.trim().length < 3) {
81
+ success = false;
82
+ errorMessage = 'Username must be at least 3 characters long';
83
+ } else if (!age || age < 13 || age > 100) {
84
+ success = false;
85
+ errorMessage = 'Age must be between 13 and 100';
86
+ } else if (!password || password.length < 6 || password.length > 20) {
87
+ success = false;
88
+ errorMessage = 'Password must be 6-20 characters long';
89
+ } else if (password !== confirmPassword) {
90
+ success = false;
91
+ errorMessage = 'Passwords do not match';
92
+ }
93
+
94
+ if (session.ws) {
95
+ session.ws.send(JSON.stringify({
96
+ type: 'registration_result',
97
+ success,
98
+ message: success ? 'Registration successful! Please check your WhatsApp.' : errorMessage
99
+ }));
100
+ }
101
+
102
+ const registrationData = {
103
+ type: 'registration_complete',
104
+ sessionId,
105
+ data: {
106
+ success,
107
+ message: errorMessage,
108
+ userData: success ? {
109
+ username: username.trim(),
110
+ age: parseInt(age),
111
+ password
112
+ } : undefined
113
+ }
114
+ };
115
+
116
+ botConnections.forEach(botWs => {
117
+ try {
118
+ botWs.send(JSON.stringify(registrationData));
119
+ } catch (error) {
120
+ console.error('[WebSocket] Error sending to bot:', error);
121
+ }
122
+ });
123
+
124
+ setTimeout(() => {
125
+ sessions.delete(sessionId);
126
+ }, 5000);
127
+ }
128
+
129
+ function cleanup(ws: ServerWebSocket) {
130
+ botConnections.delete(ws);
131
+
132
+ for (const [_, session] of sessions.entries()) {
133
+ if (session.ws === ws) {
134
+ session.ws = undefined;
135
+ }
136
+ }
137
+ }
138
+
139
+ setInterval(() => {
140
+ const now = Date.now();
141
+ for (const [sessionId, session] of sessions.entries()) {
142
+ if (now - session.createdAt > 600000) {
143
+ sessions.delete(sessionId);
144
+ console.log('[WebSocket] Cleaned up expired session:', sessionId);
145
+ }
146
+ }
147
+ }, 60000);
tsconfig.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "types": ["node", "bun"],
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "noEmit": true,
14
+ "jsx": "react-jsx",
15
+ "strict": true,
16
+ "noUnusedLocals": true,
17
+ "noUnusedParameters": true,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "baseUrl": ".",
20
+ "paths": {
21
+ "@/*": ["./src/*"]
22
+ }
23
+ },
24
+ "include": ["src"],
25
+ "references": [{ "path": "./tsconfig.node.json" }]
26
+ }
tsconfig.node.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
vite.config.ts ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+ import path from 'path'
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ resolve: {
8
+ alias: {
9
+ '@': path.resolve(__dirname, './src'),
10
+ },
11
+ },
12
+ server: {
13
+ port: 7860,
14
+ host: true
15
+ },
16
+ build: {
17
+ outDir: 'dist/public',
18
+ emptyOutDir: true,
19
+ }
20
+ })