···
51
51
"@atproto/oauth-client-node": "^0.2.16",
52
52
"@atproto/syntax": "^0.4.0",
53
53
"@fuxui/base": "^0.0.7",
54
54
+
"@fuxui/colors": "^0.1.7",
54
55
"@fuxui/social": "^0.0.9",
55
56
"@libsql/client": "^0.14.0",
56
57
"@oslojs/encoding": "^1.1.0",
···
20
20
'@fuxui/base':
21
21
specifier: ^0.0.7
22
22
version: 0.0.7(svelte@5.28.2)(tailwindcss@4.1.5)
23
23
+
'@fuxui/colors':
24
24
+
specifier: ^0.1.7
25
25
+
version: 0.1.7(svelte@5.28.2)(tailwindcss@4.1.5)
23
26
'@fuxui/social':
24
27
specifier: ^0.0.9
25
28
version: 0.0.9(svelte@5.28.2)(tailwindcss@4.1.5)
···
686
689
svelte: '>=5'
687
690
tailwindcss: '>=3'
688
691
692
692
+
'@fuxui/colors@0.1.7':
693
693
+
resolution: {integrity: sha512-nudN3g26OgPXxRJK20QQ9DzVls1uIHS06mPAv+1feBCwXN44E4q6UF0CjuKPV27pq3itxFPkgnX7r2PTidc5WQ==, tarball: https://registry.npmjs.org/@fuxui/colors/-/colors-0.1.7.tgz}
694
694
+
peerDependencies:
695
695
+
svelte: '>=5'
696
696
+
tailwindcss: '>=3'
697
697
+
689
698
'@fuxui/social@0.0.9':
690
699
resolution: {integrity: sha512-fWvXr0B+vUKX4sU+fymeLxpO2Z5/BR4ix+iCq/zdX3wpERJqr228+btU9SVnNllVjulspdnnrrrPJcIioNZBIw==, tarball: https://registry.npmjs.org/@fuxui/social/-/social-0.0.9.tgz}
691
700
peerDependencies:
···
1056
1065
resolution: {integrity: sha512-FE1stRoqdHSb7RxesMfCXE8icwI1W6zGE/512ae3ZDrpkQYTTYeSyUJPRCjZd8CwVAhpDUbi1YR8pcZioFJQ/w==, tarball: https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.5.tgz}
1057
1066
peerDependencies:
1058
1067
vite: ^5.2.0 || ^6
1068
1068
+
1069
1069
+
'@texel/color@1.1.10':
1070
1070
+
resolution: {integrity: sha512-0du+jhP68nvdXGoS/dxAyqkmWWzsogtU3chygmNf/u4QtDIbG1e5OfcVIWfx29B5ANCLEDOPEQIvOhrvwhlORg==, tarball: https://registry.npmjs.org/@texel/color/-/color-1.1.10.tgz}
1059
1071
1060
1072
'@tiptap/core@2.11.9':
1061
1073
resolution: {integrity: sha512-UZSxQLLyJst47xep3jlyKM6y1ebZnmvbGsB7njBVjfxf5H+4yFpRJwwNqrBHM/vyU55LCtPChojqaYC1wXLf6g==, tarball: https://registry.npmjs.org/@tiptap/core/-/core-2.11.9.tgz}
···
3228
3240
tailwind-variants: 1.0.0(tailwindcss@4.1.5)
3229
3241
tailwindcss: 4.1.5
3230
3242
3243
3243
+
'@fuxui/colors@0.1.7(svelte@5.28.2)(tailwindcss@4.1.5)':
3244
3244
+
dependencies:
3245
3245
+
'@fuxui/base': 0.0.7(svelte@5.28.2)(tailwindcss@4.1.5)
3246
3246
+
'@texel/color': 1.1.10
3247
3247
+
'@use-gesture/vanilla': 10.3.1
3248
3248
+
bits-ui: 1.4.4(svelte@5.28.2)
3249
3249
+
svelte: 5.28.2
3250
3250
+
tailwindcss: 4.1.5
3251
3251
+
3231
3252
'@fuxui/social@0.0.9(svelte@5.28.2)(tailwindcss@4.1.5)':
3232
3253
dependencies:
3233
3254
'@atproto/api': 0.15.5
···
3563
3584
'@tailwindcss/oxide': 4.1.5
3564
3585
tailwindcss: 4.1.5
3565
3586
vite: 6.3.4(@types/node@22.15.3)(jiti@2.4.2)(lightningcss@1.29.2)
3587
3587
+
3588
3588
+
'@texel/color@1.1.10': {}
3566
3589
3567
3590
'@tiptap/core@2.11.9(@tiptap/pm@2.11.9)':
3568
3591
dependencies:
···
4
4
5
5
@source "../node_modules/@fuxui";
6
6
7
7
-
@theme {
8
8
-
--color-base-50: var(--color-zinc-50);
9
9
-
--color-base-100: var(--color-zinc-100);
10
10
-
--color-base-200: var(--color-zinc-200);
11
11
-
--color-base-300: var(--color-zinc-300);
12
12
-
--color-base-400: var(--color-zinc-400);
13
13
-
--color-base-500: var(--color-zinc-500);
14
14
-
--color-base-600: var(--color-zinc-600);
15
15
-
--color-base-700: var(--color-zinc-700);
16
16
-
--color-base-800: var(--color-zinc-800);
17
17
-
--color-base-900: var(--color-zinc-900);
18
18
-
--color-base-950: var(--color-zinc-950);
7
7
+
@custom-variant dark (&:is(.dark *));
19
8
20
20
-
--color-accent-50: var(--color-emerald-50);
21
21
-
--color-accent-100: var(--color-emerald-100);
22
22
-
--color-accent-200: var(--color-emerald-200);
23
23
-
--color-accent-300: var(--color-emerald-300);
24
24
-
--color-accent-400: var(--color-emerald-400);
25
25
-
--color-accent-500: var(--color-emerald-500);
26
26
-
--color-accent-600: var(--color-emerald-600);
27
27
-
--color-accent-700: var(--color-emerald-700);
28
28
-
--color-accent-800: var(--color-emerald-800);
29
29
-
--color-accent-900: var(--color-emerald-900);
30
30
-
--color-accent-950: var(--color-emerald-950);
9
9
+
@theme inline {
10
10
+
--color-base-50: var(--base-50);
11
11
+
--color-base-100: var(--base-100);
12
12
+
--color-base-200: var(--base-200);
13
13
+
--color-base-300: var(--base-300);
14
14
+
--color-base-400: var(--base-400);
15
15
+
--color-base-500: var(--base-500);
16
16
+
--color-base-600: var(--base-600);
17
17
+
--color-base-700: var(--base-700);
18
18
+
--color-base-800: var(--base-800);
19
19
+
--color-base-900: var(--base-900);
20
20
+
--color-base-950: var(--base-950);
21
21
+
22
22
+
--color-accent-50: var(--accent-50);
23
23
+
--color-accent-100: var(--accent-100);
24
24
+
--color-accent-200: var(--accent-200);
25
25
+
--color-accent-300: var(--accent-300);
26
26
+
--color-accent-400: var(--accent-400);
27
27
+
--color-accent-500: var(--accent-500);
28
28
+
--color-accent-600: var(--accent-600);
29
29
+
--color-accent-700: var(--accent-700);
30
30
+
--color-accent-800: var(--accent-800);
31
31
+
--color-accent-900: var(--accent-900);
32
32
+
--color-accent-950: var(--accent-950);
31
33
}
34
34
+
35
35
+
@layer base {
36
36
+
:root {
37
37
+
--accent-50: var(--color-pink-50);
38
38
+
--accent-100: var(--color-pink-100);
39
39
+
--accent-200: var(--color-pink-200);
40
40
+
--accent-300: var(--color-pink-300);
41
41
+
--accent-400: var(--color-pink-400);
42
42
+
--accent-500: var(--color-pink-500);
43
43
+
--accent-600: var(--color-pink-600);
44
44
+
--accent-700: var(--color-pink-700);
45
45
+
--accent-800: var(--color-pink-800);
46
46
+
--accent-900: var(--color-pink-900);
47
47
+
--accent-950: var(--color-pink-950);
48
48
+
49
49
+
--base-50: var(--color-stone-50);
50
50
+
--base-100: var(--color-stone-100);
51
51
+
--base-200: var(--color-stone-200);
52
52
+
--base-300: var(--color-stone-300);
53
53
+
--base-400: var(--color-stone-400);
54
54
+
--base-500: var(--color-stone-500);
55
55
+
--base-600: var(--color-stone-600);
56
56
+
--base-700: var(--color-stone-700);
57
57
+
--base-800: var(--color-stone-800);
58
58
+
--base-900: var(--color-stone-900);
59
59
+
--base-950: var(--color-stone-950);
60
60
+
}
61
61
+
62
62
+
.red {
63
63
+
--accent-50: var(--color-red-50);
64
64
+
--accent-100: var(--color-red-100);
65
65
+
--accent-200: var(--color-red-200);
66
66
+
--accent-300: var(--color-red-300);
67
67
+
--accent-400: var(--color-red-400);
68
68
+
--accent-500: var(--color-red-500);
69
69
+
--accent-600: var(--color-red-600);
70
70
+
--accent-700: var(--color-red-700);
71
71
+
--accent-800: var(--color-red-800);
72
72
+
--accent-900: var(--color-red-900);
73
73
+
--accent-950: var(--color-red-950);
74
74
+
}
75
75
+
76
76
+
.orange {
77
77
+
--accent-50: var(--color-orange-50);
78
78
+
--accent-100: var(--color-orange-100);
79
79
+
--accent-200: var(--color-orange-200);
80
80
+
--accent-300: var(--color-orange-300);
81
81
+
--accent-400: var(--color-orange-400);
82
82
+
--accent-500: var(--color-orange-500);
83
83
+
--accent-600: var(--color-orange-600);
84
84
+
--accent-700: var(--color-orange-700);
85
85
+
--accent-800: var(--color-orange-800);
86
86
+
--accent-900: var(--color-orange-900);
87
87
+
--accent-950: var(--color-orange-950);
88
88
+
}
89
89
+
90
90
+
.amber {
91
91
+
--accent-50: var(--color-amber-50);
92
92
+
--accent-100: var(--color-amber-100);
93
93
+
--accent-200: var(--color-amber-200);
94
94
+
--accent-300: var(--color-amber-300);
95
95
+
--accent-400: var(--color-amber-400);
96
96
+
--accent-500: var(--color-amber-500);
97
97
+
--accent-600: var(--color-amber-600);
98
98
+
--accent-700: var(--color-amber-700);
99
99
+
--accent-800: var(--color-amber-800);
100
100
+
--accent-900: var(--color-amber-900);
101
101
+
--accent-950: var(--color-amber-950);
102
102
+
}
103
103
+
104
104
+
.yellow {
105
105
+
--accent-50: var(--color-yellow-50);
106
106
+
--accent-100: var(--color-yellow-100);
107
107
+
--accent-200: var(--color-yellow-200);
108
108
+
--accent-300: var(--color-yellow-300);
109
109
+
--accent-400: var(--color-yellow-400);
110
110
+
--accent-500: var(--color-yellow-500);
111
111
+
--accent-600: var(--color-yellow-600);
112
112
+
--accent-700: var(--color-yellow-700);
113
113
+
--accent-800: var(--color-yellow-800);
114
114
+
--accent-900: var(--color-yellow-900);
115
115
+
--accent-950: var(--color-yellow-950);
116
116
+
}
117
117
+
118
118
+
.lime {
119
119
+
--accent-50: var(--color-lime-50);
120
120
+
--accent-100: var(--color-lime-100);
121
121
+
--accent-200: var(--color-lime-200);
122
122
+
--accent-300: var(--color-lime-300);
123
123
+
--accent-400: var(--color-lime-400);
124
124
+
--accent-500: var(--color-lime-500);
125
125
+
--accent-600: var(--color-lime-600);
126
126
+
--accent-700: var(--color-lime-700);
127
127
+
--accent-800: var(--color-lime-800);
128
128
+
--accent-900: var(--color-lime-900);
129
129
+
--accent-950: var(--color-lime-950);
130
130
+
}
131
131
+
132
132
+
.green {
133
133
+
--accent-50: var(--color-green-50);
134
134
+
--accent-100: var(--color-green-100);
135
135
+
--accent-200: var(--color-green-200);
136
136
+
--accent-300: var(--color-green-300);
137
137
+
--accent-400: var(--color-green-400);
138
138
+
--accent-500: var(--color-green-500);
139
139
+
--accent-600: var(--color-green-600);
140
140
+
--accent-700: var(--color-green-700);
141
141
+
--accent-800: var(--color-green-800);
142
142
+
--accent-900: var(--color-green-900);
143
143
+
--accent-950: var(--color-green-950);
144
144
+
}
145
145
+
146
146
+
.emerald {
147
147
+
--accent-50: var(--color-emerald-50);
148
148
+
--accent-100: var(--color-emerald-100);
149
149
+
--accent-200: var(--color-emerald-200);
150
150
+
--accent-300: var(--color-emerald-300);
151
151
+
--accent-400: var(--color-emerald-400);
152
152
+
--accent-500: var(--color-emerald-500);
153
153
+
--accent-600: var(--color-emerald-600);
154
154
+
--accent-700: var(--color-emerald-700);
155
155
+
--accent-800: var(--color-emerald-800);
156
156
+
--accent-900: var(--color-emerald-900);
157
157
+
--accent-950: var(--color-emerald-950);
158
158
+
}
159
159
+
160
160
+
.teal {
161
161
+
--accent-50: var(--color-teal-50);
162
162
+
--accent-100: var(--color-teal-100);
163
163
+
--accent-200: var(--color-teal-200);
164
164
+
--accent-300: var(--color-teal-300);
165
165
+
--accent-400: var(--color-teal-400);
166
166
+
--accent-500: var(--color-teal-500);
167
167
+
--accent-600: var(--color-teal-600);
168
168
+
--accent-700: var(--color-teal-700);
169
169
+
--accent-800: var(--color-teal-800);
170
170
+
--accent-900: var(--color-teal-900);
171
171
+
--accent-950: var(--color-teal-950);
172
172
+
}
173
173
+
174
174
+
.cyan {
175
175
+
--accent-50: var(--color-cyan-50);
176
176
+
--accent-100: var(--color-cyan-100);
177
177
+
--accent-200: var(--color-cyan-200);
178
178
+
--accent-300: var(--color-cyan-300);
179
179
+
--accent-400: var(--color-cyan-400);
180
180
+
--accent-500: var(--color-cyan-500);
181
181
+
--accent-600: var(--color-cyan-600);
182
182
+
--accent-700: var(--color-cyan-700);
183
183
+
--accent-800: var(--color-cyan-800);
184
184
+
--accent-900: var(--color-cyan-900);
185
185
+
--accent-950: var(--color-cyan-950);
186
186
+
}
187
187
+
188
188
+
.sky {
189
189
+
--accent-50: var(--color-sky-50);
190
190
+
--accent-100: var(--color-sky-100);
191
191
+
--accent-200: var(--color-sky-200);
192
192
+
--accent-300: var(--color-sky-300);
193
193
+
--accent-400: var(--color-sky-400);
194
194
+
--accent-500: var(--color-sky-500);
195
195
+
--accent-600: var(--color-sky-600);
196
196
+
--accent-700: var(--color-sky-700);
197
197
+
--accent-800: var(--color-sky-800);
198
198
+
--accent-900: var(--color-sky-900);
199
199
+
--accent-950: var(--color-sky-950);
200
200
+
}
201
201
+
.blue {
202
202
+
--accent-50: var(--color-blue-50);
203
203
+
--accent-100: var(--color-blue-100);
204
204
+
--accent-200: var(--color-blue-200);
205
205
+
--accent-300: var(--color-blue-300);
206
206
+
--accent-400: var(--color-blue-400);
207
207
+
--accent-500: var(--color-blue-500);
208
208
+
--accent-600: var(--color-blue-600);
209
209
+
--accent-700: var(--color-blue-700);
210
210
+
--accent-800: var(--color-blue-800);
211
211
+
--accent-900: var(--color-blue-900);
212
212
+
--accent-950: var(--color-blue-950);
213
213
+
}
214
214
+
215
215
+
.indigo {
216
216
+
--accent-50: var(--color-indigo-50);
217
217
+
--accent-100: var(--color-indigo-100);
218
218
+
--accent-200: var(--color-indigo-200);
219
219
+
--accent-300: var(--color-indigo-300);
220
220
+
--accent-400: var(--color-indigo-400);
221
221
+
--accent-500: var(--color-indigo-500);
222
222
+
--accent-600: var(--color-indigo-600);
223
223
+
--accent-700: var(--color-indigo-700);
224
224
+
--accent-800: var(--color-indigo-800);
225
225
+
--accent-900: var(--color-indigo-900);
226
226
+
--accent-950: var(--color-indigo-950);
227
227
+
}
228
228
+
229
229
+
.violet {
230
230
+
--accent-50: var(--color-violet-50);
231
231
+
--accent-100: var(--color-violet-100);
232
232
+
--accent-200: var(--color-violet-200);
233
233
+
--accent-300: var(--color-violet-300);
234
234
+
--accent-400: var(--color-violet-400);
235
235
+
--accent-500: var(--color-violet-500);
236
236
+
--accent-600: var(--color-violet-600);
237
237
+
--accent-700: var(--color-violet-700);
238
238
+
--accent-800: var(--color-violet-800);
239
239
+
--accent-900: var(--color-violet-900);
240
240
+
--accent-950: var(--color-violet-950);
241
241
+
}
242
242
+
243
243
+
.purple {
244
244
+
--accent-50: var(--color-purple-50);
245
245
+
--accent-100: var(--color-purple-100);
246
246
+
--accent-200: var(--color-purple-200);
247
247
+
--accent-300: var(--color-purple-300);
248
248
+
--accent-400: var(--color-purple-400);
249
249
+
--accent-500: var(--color-purple-500);
250
250
+
--accent-600: var(--color-purple-600);
251
251
+
--accent-700: var(--color-purple-700);
252
252
+
--accent-800: var(--color-purple-800);
253
253
+
--accent-900: var(--color-purple-900);
254
254
+
--accent-950: var(--color-purple-950);
255
255
+
}
256
256
+
257
257
+
.fuchsia {
258
258
+
--accent-50: var(--color-fuchsia-50);
259
259
+
--accent-100: var(--color-fuchsia-100);
260
260
+
--accent-200: var(--color-fuchsia-200);
261
261
+
--accent-300: var(--color-fuchsia-300);
262
262
+
--accent-400: var(--color-fuchsia-400);
263
263
+
--accent-500: var(--color-fuchsia-500);
264
264
+
--accent-600: var(--color-fuchsia-600);
265
265
+
--accent-700: var(--color-fuchsia-700);
266
266
+
--accent-800: var(--color-fuchsia-800);
267
267
+
--accent-900: var(--color-fuchsia-900);
268
268
+
--accent-950: var(--color-fuchsia-950);
269
269
+
}
270
270
+
271
271
+
.pink {
272
272
+
--accent-50: var(--color-pink-50);
273
273
+
--accent-100: var(--color-pink-100);
274
274
+
--accent-200: var(--color-pink-200);
275
275
+
--accent-300: var(--color-pink-300);
276
276
+
--accent-400: var(--color-pink-400);
277
277
+
--accent-500: var(--color-pink-500);
278
278
+
--accent-600: var(--color-pink-600);
279
279
+
--accent-700: var(--color-pink-700);
280
280
+
--accent-800: var(--color-pink-800);
281
281
+
--accent-900: var(--color-pink-900);
282
282
+
--accent-950: var(--color-pink-950);
283
283
+
}
284
284
+
285
285
+
.rose {
286
286
+
--accent-50: var(--color-rose-50);
287
287
+
--accent-100: var(--color-rose-100);
288
288
+
--accent-200: var(--color-rose-200);
289
289
+
--accent-300: var(--color-rose-300);
290
290
+
--accent-400: var(--color-rose-400);
291
291
+
--accent-500: var(--color-rose-500);
292
292
+
--accent-600: var(--color-rose-600);
293
293
+
--accent-700: var(--color-rose-700);
294
294
+
--accent-800: var(--color-rose-800);
295
295
+
--accent-900: var(--color-rose-900);
296
296
+
--accent-950: var(--color-rose-950);
297
297
+
}
298
298
+
299
299
+
.gray {
300
300
+
--base-50: var(--color-gray-50);
301
301
+
--base-100: var(--color-gray-100);
302
302
+
--base-200: var(--color-gray-200);
303
303
+
--base-300: var(--color-gray-300);
304
304
+
--base-400: var(--color-gray-400);
305
305
+
--base-500: var(--color-gray-500);
306
306
+
--base-600: var(--color-gray-600);
307
307
+
--base-700: var(--color-gray-700);
308
308
+
--base-800: var(--color-gray-800);
309
309
+
--base-900: var(--color-gray-900);
310
310
+
--base-950: var(--color-gray-950);
311
311
+
}
312
312
+
313
313
+
.zinc {
314
314
+
--base-50: var(--color-zinc-50);
315
315
+
--base-100: var(--color-zinc-100);
316
316
+
--base-200: var(--color-zinc-200);
317
317
+
--base-300: var(--color-zinc-300);
318
318
+
--base-400: var(--color-zinc-400);
319
319
+
--base-500: var(--color-zinc-500);
320
320
+
--base-600: var(--color-zinc-600);
321
321
+
--base-700: var(--color-zinc-700);
322
322
+
--base-800: var(--color-zinc-800);
323
323
+
--base-900: var(--color-zinc-900);
324
324
+
--base-950: var(--color-zinc-950);
325
325
+
}
326
326
+
327
327
+
.neutral {
328
328
+
--base-50: var(--color-neutral-50);
329
329
+
--base-100: var(--color-neutral-100);
330
330
+
--base-200: var(--color-neutral-200);
331
331
+
--base-300: var(--color-neutral-300);
332
332
+
--base-400: var(--color-neutral-400);
333
333
+
--base-500: var(--color-neutral-500);
334
334
+
--base-600: var(--color-neutral-600);
335
335
+
--base-700: var(--color-neutral-700);
336
336
+
--base-800: var(--color-neutral-800);
337
337
+
--base-900: var(--color-neutral-900);
338
338
+
--base-950: var(--color-neutral-950);
339
339
+
}
340
340
+
341
341
+
.stone {
342
342
+
--base-50: var(--color-stone-50);
343
343
+
--base-100: var(--color-stone-100);
344
344
+
--base-200: var(--color-stone-200);
345
345
+
--base-300: var(--color-stone-300);
346
346
+
--base-400: var(--color-stone-400);
347
347
+
--base-500: var(--color-stone-500);
348
348
+
--base-600: var(--color-stone-600);
349
349
+
--base-700: var(--color-stone-700);
350
350
+
--base-800: var(--color-stone-800);
351
351
+
--base-900: var(--color-stone-900);
352
352
+
--base-950: var(--color-stone-950);
353
353
+
}
354
354
+
355
355
+
.slate {
356
356
+
--base-50: var(--color-slate-50);
357
357
+
--base-100: var(--color-slate-100);
358
358
+
--base-200: var(--color-slate-200);
359
359
+
--base-300: var(--color-slate-300);
360
360
+
--base-400: var(--color-slate-400);
361
361
+
--base-500: var(--color-slate-500);
362
362
+
--base-600: var(--color-slate-600);
363
363
+
--base-700: var(--color-slate-700);
364
364
+
--base-800: var(--color-slate-800);
365
365
+
--base-900: var(--color-slate-900);
366
366
+
--base-950: var(--color-slate-950);
367
367
+
}
368
368
+
}
···
1
1
<!doctype html>
2
2
-
<html lang="en" class="dark">
2
2
+
<html lang="en">
3
3
<head>
4
4
<meta charset="utf-8" />
5
5
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
6
6
<meta name="viewport" content="width=device-width, initial-scale=1" />
7
7
%sveltekit.head%
8
8
+
9
9
+
10
10
+
<script>
11
11
+
let dark = localStorage.getItem('darkMode');
12
12
+
if (dark) {
13
13
+
dark = JSON.parse(dark);
14
14
+
} else {
15
15
+
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
16
16
+
}
17
17
+
18
18
+
var root = document.getElementsByTagName('html')[0];
19
19
+
if (dark) {
20
20
+
root.classList.add('dark');
21
21
+
} else {
22
22
+
root.classList.remove('dark');
23
23
+
}
24
24
+
25
25
+
// get accent color from local storage
26
26
+
let accentColor = localStorage.getItem('accentColor');
27
27
+
if (accentColor) {
28
28
+
accentColor = JSON.parse(accentColor);
29
29
+
root.classList.add(accentColor);
30
30
+
}
31
31
+
32
32
+
// get base color from local storage
33
33
+
let baseColor = localStorage.getItem('baseColor');
34
34
+
if (baseColor) {
35
35
+
baseColor = JSON.parse(baseColor);
36
36
+
root.classList.add(baseColor);
37
37
+
}
38
38
+
</script>
8
39
</head>
9
40
<body data-sveltekit-preload-data="hover" class="bg-base-50 dark:bg-base-950">
10
41
<div style="display: contents">%sveltekit.body%</div>
···
1
1
<script lang="ts">
2
2
+
import { toast, Subheading, Input, Button } from '@fuxui/base';
3
3
+
import { editingState } from '../routes/state.svelte';
4
4
+
2
5
let { links } = $props();
6
6
+
7
7
+
let link = $state('');
8
8
+
9
9
+
let loading = $state(false);
10
10
+
11
11
+
async function addLink(event: Event) {
12
12
+
event.preventDefault();
13
13
+
if (loading) return;
14
14
+
loading = true;
15
15
+
16
16
+
// check if link is already in the list
17
17
+
if (editingState.links.some((l) => l.url === link)) {
18
18
+
toast.error('Link already exists');
19
19
+
loading = false;
20
20
+
return;
21
21
+
}
22
22
+
23
23
+
const response = await fetch(`/api/get-og?url=${link}`);
24
24
+
const og = await response.json();
25
25
+
26
26
+
if (!og.success) {
27
27
+
toast.error('Invalid link');
28
28
+
loading = false;
29
29
+
return;
30
30
+
}
31
31
+
32
32
+
editingState.links.push({
33
33
+
url: link,
34
34
+
title: og.ogTitle,
35
35
+
description: og.ogDescription,
36
36
+
image: og.ogImage?.[0]?.url
37
37
+
});
38
38
+
39
39
+
// save links to local storage
40
40
+
localStorage.setItem('links', JSON.stringify(editingState.links));
41
41
+
42
42
+
link = '';
43
43
+
loading = false;
44
44
+
45
45
+
toast('Link added');
46
46
+
47
47
+
console.log(editingState.links);
48
48
+
}
49
49
+
50
50
+
function removeLink(url: string) {
51
51
+
editingState.links = editingState.links.filter((l) => l.url !== url);
52
52
+
localStorage.setItem('links', JSON.stringify(editingState.links));
53
53
+
}
3
54
</script>
4
55
56
56
+
<div class="px-2">
57
57
+
<Subheading class="mt-4 mb-4">Add a link:</Subheading>
58
58
+
<form onsubmit={addLink} class="flex gap-2">
59
59
+
<Input bind:value={link} name="link" class="grow" />
60
60
+
<Button type="submit" disabled={loading}>{loading ? 'Adding...' : 'Add'}</Button>
61
61
+
</form>
62
62
+
</div>
5
63
<div class="mt-6 flex flex-col gap-6 px-4 text-white">
6
64
{#each links as link}
7
7
-
<div>
65
65
+
<div class="relative">
8
66
<a href={link.url} target="_blank" class="text-accent-600 dark:text-accent-400 font-medium">
9
67
{link.title}
10
68
</a>
···
12
70
<div class="text-base-600 dark:text-base-400 mt-1 text-sm">
13
71
{link.description}
14
72
</div>
73
73
+
74
74
+
<Button
75
75
+
onclick={() => removeLink(link.url)}
76
76
+
variant="secondary"
77
77
+
size="iconSm"
78
78
+
class="absolute top-0 right-0"
79
79
+
>
80
80
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
81
81
+
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
82
82
+
</svg>
83
83
+
84
84
+
85
85
+
<span class="sr-only">remove link</span>
86
86
+
</Button>
15
87
</div>
16
88
{/each}
17
89
</div>
···
1
1
+
<script lang="ts">
2
2
+
import { ThemeToggle, Navbar, Button } from '@fuxui/base';
3
3
+
4
4
+
import ThemeSelectDropdown from './ThemeSelectDropdown.svelte';
5
5
+
</script>
6
6
+
7
7
+
<Navbar>
8
8
+
<div class="flex items-center gap-2">
9
9
+
<!-- <Button variant="link" class="block font-normal lg:hidden backdrop-blur-none" popovertarget="mobile-menu">
10
10
+
<svg
11
11
+
xmlns="http://www.w3.org/2000/svg"
12
12
+
viewBox="0 0 24 24"
13
13
+
fill="currentColor"
14
14
+
class="size-6!"
15
15
+
>
16
16
+
<path
17
17
+
fill-rule="evenodd"
18
18
+
d="M3 9a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 9Zm0 6.75a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75a.75.75 0 0 1-.75-.75Z"
19
19
+
clip-rule="evenodd"
20
20
+
></path>
21
21
+
</svg>
22
22
+
</Button>
23
23
+
24
24
+
<Logo class={showLogo ? 'lg:ml-5' : 'lg:hidden'} /> -->
25
25
+
</div>
26
26
+
<div class="flex items-center gap-3">
27
27
+
<ThemeSelectDropdown />
28
28
+
<ThemeToggle class="backdrop-blur-none" />
29
29
+
<Button size="lg">Publish</Button>
30
30
+
31
31
+
<!-- <Github href="https://github.com/flo-bit/ui-kit" class="mr-2 p-2" /> -->
32
32
+
</div>
33
33
+
</Navbar>
···
1
1
<script lang="ts">
2
2
-
import { AtpBaseClient, type Agent } from '@atproto/api';
3
3
-
import type { FeedViewPost } from '@atproto/api/dist/client/types/app/bsky/feed/defs';
4
4
-
import { blueskyPostToPostData, Post, type PostData } from '@fuxui/social';
5
5
-
import { onMount } from 'svelte';
6
6
-
7
7
-
export async function getPostsOfUser({
8
8
-
actor,
9
9
-
cursor,
10
10
-
limit = 20
11
11
-
}: {
12
12
-
actor: string;
13
13
-
cursor?: string;
14
14
-
limit?: number;
15
15
-
}) {
16
16
-
let agent = new AtpBaseClient({ service: 'https://api.bsky.app' });
17
17
-
const perLimit = limit > 100 ? 100 : limit;
18
18
-
const posts: FeedViewPost[] = [];
19
19
-
do {
20
20
-
const { data } = await agent.app.bsky.feed.getAuthorFeed({
21
21
-
actor,
22
22
-
cursor,
23
23
-
limit: perLimit,
24
24
-
filter: 'posts_no_replies'
25
25
-
});
26
26
-
posts.push(...data.feed);
27
27
-
cursor = data.cursor;
28
28
-
} while (cursor && posts.length < limit);
29
29
-
return { feed: posts, cursor };
30
30
-
}
31
31
-
32
32
-
let { did } = $props();
33
33
-
34
34
-
let blueskyPosts: PostData[] = $state([]);
35
35
-
36
36
-
onMount(async () => {
37
37
-
const posts = await getPostsOfUser({ actor: did });
38
38
-
console.log(posts);
2
2
+
import { Post, type PostData } from '@fuxui/social';
39
3
40
40
-
blueskyPosts = posts.feed.map((post) => {
41
41
-
console.log(post);
42
42
-
return blueskyPostToPostData(post.post);
43
43
-
});
44
44
-
});
4
4
+
let { posts }: { posts: PostData[] } = $props();
45
5
</script>
46
6
47
7
<div class="mt-4">
48
48
-
{#if blueskyPosts}
49
49
-
{#each blueskyPosts as post}
50
50
-
<Post data={post} class="py-4">hello</Post>
51
51
-
{/each}
52
52
-
{/if}
8
8
+
{#if posts}
9
9
+
{#each posts as post}
10
10
+
<Post data={post} class="py-4">hello</Post>
11
11
+
{/each}
12
12
+
{/if}
53
13
</div>
···
1
1
+
<script lang="ts" module>
2
2
+
let accentColor = $state({
3
3
+
class: '',
4
4
+
label: ''
5
5
+
});
6
6
+
7
7
+
let baseColor = $state({
8
8
+
class: '',
9
9
+
label: ''
10
10
+
});
11
11
+
</script>
12
12
+
13
13
+
<script lang="ts">
14
14
+
import { Subheading, Paragraph } from '@fuxui/base';
15
15
+
import { ColorSelect } from '@fuxui/colors';
16
16
+
import { onMount } from 'svelte';
17
17
+
18
18
+
let accentColors = [
19
19
+
{ class: 'text-red-500', label: 'red' },
20
20
+
{ class: 'text-orange-500', label: 'orange' },
21
21
+
{ class: 'text-amber-500', label: 'amber' },
22
22
+
{ class: 'text-yellow-500', label: 'yellow' },
23
23
+
{ class: 'text-lime-500', label: 'lime' },
24
24
+
{ class: 'text-green-500', label: 'green' },
25
25
+
{ class: 'text-emerald-500', label: 'emerald' },
26
26
+
{ class: 'text-teal-500', label: 'teal' },
27
27
+
{ class: 'text-cyan-500', label: 'cyan' },
28
28
+
{ class: 'text-sky-500', label: 'sky' },
29
29
+
{ class: 'text-blue-500', label: 'blue' },
30
30
+
{ class: 'text-indigo-500', label: 'indigo' },
31
31
+
{ class: 'text-violet-500', label: 'violet' },
32
32
+
{ class: 'text-purple-500', label: 'purple' },
33
33
+
{ class: 'text-fuchsia-500', label: 'fuchsia' },
34
34
+
{ class: 'text-pink-500', label: 'pink' },
35
35
+
{ class: 'text-rose-500', label: 'rose' }
36
36
+
];
37
37
+
38
38
+
let baseColors = [
39
39
+
{ class: 'text-gray-500', label: 'gray' },
40
40
+
{ class: 'text-stone-500', label: 'stone' },
41
41
+
{ class: 'text-zinc-500', label: 'zinc' },
42
42
+
{ class: 'text-neutral-500', label: 'neutral' },
43
43
+
{ class: 'text-slate-500', label: 'slate' }
44
44
+
];
45
45
+
46
46
+
onMount(() => {
47
47
+
let savedAccentColor = localStorage.getItem('accentColor');
48
48
+
if (savedAccentColor) {
49
49
+
accentColor.label = JSON.parse(savedAccentColor);
50
50
+
} else {
51
51
+
accentColor.label = 'pink';
52
52
+
}
53
53
+
54
54
+
let savedBaseColor = localStorage.getItem('baseColor');
55
55
+
if (savedBaseColor) {
56
56
+
baseColor.label = JSON.parse(savedBaseColor);
57
57
+
} else {
58
58
+
baseColor.label = 'stone';
59
59
+
}
60
60
+
});
61
61
+
62
62
+
let { showTitle = true } = $props();
63
63
+
</script>
64
64
+
65
65
+
{#if showTitle}
66
66
+
<Subheading class="mb-4">Select Theme</Subheading>
67
67
+
{/if}
68
68
+
69
69
+
<Paragraph class="mb-2">Accent Color</Paragraph>
70
70
+
<ColorSelect
71
71
+
bind:selected={accentColor}
72
72
+
colors={accentColors}
73
73
+
onselected={(color, previous) => {
74
74
+
if (typeof previous === 'string' || typeof color === 'string') {
75
75
+
return;
76
76
+
}
77
77
+
78
78
+
document.documentElement.classList.remove(previous.label.toLowerCase());
79
79
+
document.documentElement.classList.add(color.label.toLowerCase());
80
80
+
81
81
+
localStorage.setItem('accentColor', JSON.stringify(color.label));
82
82
+
83
83
+
window.dispatchEvent(
84
84
+
new CustomEvent('theme-changed', { detail: { accentColor: color.label } })
85
85
+
);
86
86
+
}}
87
87
+
class="w-64"
88
88
+
/>
89
89
+
90
90
+
<Paragraph class="mt-4 mb-2">Base Color</Paragraph>
91
91
+
<ColorSelect
92
92
+
bind:selected={baseColor}
93
93
+
colors={baseColors}
94
94
+
onselected={(color, previous) => {
95
95
+
if (typeof previous === 'string' || typeof color === 'string') {
96
96
+
return;
97
97
+
}
98
98
+
99
99
+
document.documentElement.classList.remove(previous.label.toLowerCase());
100
100
+
document.documentElement.classList.add(color.label.toLowerCase());
101
101
+
102
102
+
localStorage.setItem('baseColor', JSON.stringify(color.label));
103
103
+
104
104
+
window.dispatchEvent(new CustomEvent('theme-changed', { detail: { baseColor: color.label } }));
105
105
+
}}
106
106
+
/>
···
1
1
+
<script>
2
2
+
import { buttonVariants, Popover, cn } from '@fuxui/base';
3
3
+
import SelectTheme from './SelectTheme.svelte';
4
4
+
</script>
5
5
+
6
6
+
<Popover>
7
7
+
{#snippet child({ props })}
8
8
+
<button {...props}
9
9
+
class={cn(
10
10
+
buttonVariants({ variant: 'link', size: 'default' }),
11
11
+
'flex cursor-pointer items-center gap-0 -space-x-2 backdrop-blur-none'
12
12
+
)}
13
13
+
>
14
14
+
<div
15
15
+
class=" from-accent-500 to-accent-600 border-accent-700 dark:border-accent-400 z-10 size-6 rounded-full border bg-gradient-to-b"
16
16
+
></div>
17
17
+
18
18
+
<div
19
19
+
class=" from-base-500 to-base-600 border-base-700 dark:border-base-400 size-6 rounded-full border bg-gradient-to-b"
20
20
+
></div>
21
21
+
</button>
22
22
+
{/snippet}
23
23
+
<!-- add class w-72? -->
24
24
+
<SelectTheme showTitle={false} />
25
25
+
</Popover>
···
1
1
<script lang="ts">
2
2
-
import { Badge, Button, Heading, Input, Subheading, Tabs } from '@fuxui/base';
3
3
-
import { BlueskyLogin, UserProfile } from '@fuxui/social';
2
2
+
import { Badge, Button, Input, Subheading, Tabs, ThemeToggle, toast, Toaster } from '@fuxui/base';
3
3
+
import { BlueskyLogin, blueskyPostToPostData, UserProfile, type PostData } from '@fuxui/social';
4
4
import { editingState } from './state.svelte.js';
5
5
import Editor from '$lib/Editor.svelte';
6
6
import Posts from '$lib/Posts.svelte';
7
7
import Links from '$lib/Links.svelte';
8
8
+
import { onMount } from 'svelte';
9
9
+
import { AtpBaseClient } from '@atproto/api';
10
10
+
import type { FeedViewPost } from '@atproto/api/dist/client/types/app/bsky/feed/defs.js';
11
11
+
import Navbar from '$lib/Navbar.svelte';
8
12
9
13
let { data } = $props();
10
14
11
15
let form = $state<HTMLFormElement | null>(null);
12
16
13
13
-
let link = $state('');
14
14
-
15
15
-
async function addLink(event: Event) {
16
16
-
event.preventDefault();
17
17
+
onMount(async () => {
18
18
+
editingState.links = JSON.parse(localStorage.getItem('links') ?? '[]');
17
19
18
18
-
// check if link is already in the list
19
19
-
if (editingState.links.some((l) => l.url === link)) {
20
20
-
return;
21
21
-
}
22
22
-
23
23
-
const response = await fetch(`/api/get-og?url=${link}`);
24
24
-
const og = await response.json();
20
20
+
if (!data.user) return;
25
21
26
26
-
if(!og.success) return;
22
22
+
const posts = await getPostsOfUser({ actor: data.user.did });
23
23
+
console.log(posts);
27
24
28
28
-
editingState.links.push({
29
29
-
url: link,
30
30
-
title: og.ogTitle,
31
31
-
description: og.ogDescription,
32
32
-
image: og.ogImage?.[0]?.url
25
25
+
blueskyPosts = posts.feed.map((post) => {
26
26
+
console.log(post);
27
27
+
return blueskyPostToPostData(post.post);
33
28
});
29
29
+
});
34
30
35
35
-
// save links to local storage
36
36
-
localStorage.setItem('links', JSON.stringify(editingState.links));
37
37
-
38
38
-
link = '';
39
39
-
40
40
-
console.log(editingState.links);
31
31
+
export async function getPostsOfUser({
32
32
+
actor,
33
33
+
cursor,
34
34
+
limit = 20
35
35
+
}: {
36
36
+
actor: string;
37
37
+
cursor?: string;
38
38
+
limit?: number;
39
39
+
}) {
40
40
+
let agent = new AtpBaseClient({ service: 'https://api.bsky.app' });
41
41
+
const perLimit = limit > 100 ? 100 : limit;
42
42
+
const posts: FeedViewPost[] = [];
43
43
+
do {
44
44
+
const { data } = await agent.app.bsky.feed.getAuthorFeed({
45
45
+
actor,
46
46
+
cursor,
47
47
+
limit: perLimit,
48
48
+
filter: 'posts_no_replies'
49
49
+
});
50
50
+
posts.push(...data.feed);
51
51
+
cursor = data.cursor;
52
52
+
} while (cursor && posts.length < limit);
53
53
+
return { feed: posts, cursor };
41
54
}
55
55
+
56
56
+
let blueskyPosts: PostData[] = $state([]);
42
57
</script>
43
58
44
44
-
<div class="mx-auto max-w-2xl">
59
59
+
<div class="mx-auto max-w-2xl py-16">
45
60
{#if !data.user}
46
61
<BlueskyLogin
47
62
login={async (handle) => {
···
68
83
<input type="hidden" name="handle" value="handle" />
69
84
</form>
70
85
{:else}
71
71
-
<Button size="lg" class="fixed top-2 right-2">Publish</Button>
72
72
-
<UserProfile class="" profile={{ ...data.user, description: '' }} />
86
86
+
<UserProfile class="" profile={{ ...data.user, description: undefined }} />
73
87
88
88
+
<div class="-mt-8">
74
89
<Tabs
75
90
active={editingState.active}
76
91
items={[
···
92
107
<div class="px-4">
93
108
{#if editingState.active === 'about'}
94
109
<div
95
95
-
class="focus-within:outline-accent-400 hover:bg-base-900/20 group focus-within:bg-accent-500/5 focus-within:hover:bg-accent-500/5 relative mt-4 rounded-2xl px-2 py-0.5 focus-within:outline"
110
110
+
class="focus-within:outline-accent-400 hover:not-focus-within:bg-base-200/40 dark:hover:not-focus-within:bg-base-900/20 group focus-within:bg-accent-500/5 relative mt-4 rounded-2xl px-2 py-0.5 focus-within:outline"
96
111
>
97
112
<Editor />
98
113
<Badge
···
104
119
</div>
105
120
{:else if editingState.active === 'links'}
106
121
<div>
107
107
-
<div class="px-2">
108
108
-
<Subheading class="mb-4 mt-4">Add a link:</Subheading>
109
109
-
<form onsubmit={addLink} class="flex gap-2">
110
110
-
<Input bind:value={link} name="link" class="grow" />
111
111
-
<Button type="submit">Add</Button>
112
112
-
</form>
113
113
-
</div>
114
122
<Links links={editingState.links} />
115
123
</div>
116
124
{:else if editingState.active === 'feed'}
117
117
-
<Posts did={data.user.did} />
125
125
+
<Posts posts={blueskyPosts} />
118
126
{/if}
119
127
</div>
120
128
121
129
<form method="POST" action="/?/logout" class="fixed right-2 bottom-2">
122
130
<Button type="submit">Logout</Button>
123
131
</form>
132
132
+
</div>
124
133
{/if}
125
134
</div>
135
135
+
136
136
+
<Toaster />
137
137
+
138
138
+
<Navbar />