+10
-9
package.json
+10
-9
package.json
···
11
11
"devDependencies": {
12
12
"@iconify-json/lucide": "^1.2.68",
13
13
"@iconify/tailwind4": "^1.0.6",
14
-
"@tailwindcss/vite": "^4.1.13",
14
+
"@tailwindcss/vite": "^4.1.14",
15
15
"prettier": "^3.6.2",
16
16
"prettier-plugin-organize-imports": "^4.3.0",
17
17
"prettier-plugin-tailwindcss": "^0.6.14",
18
-
"tailwindcss": "^4.1.13",
19
-
"typescript": "^5.9.2",
20
-
"vite": "^7.1.7",
21
-
"vite-plugin-solid": "^2.11.8"
18
+
"tailwindcss": "^4.1.14",
19
+
"typescript": "^5.9.3",
20
+
"vite": "^7.1.8",
21
+
"vite-plugin-solid": "^2.11.9"
22
22
},
23
23
"dependencies": {
24
24
"@atcute/atproto": "^3.1.4",
···
33
33
"@atcute/identity-resolver": "^1.1.3",
34
34
"@atcute/leaflet": "^1.0.8",
35
35
"@atcute/lexicon-doc": "^1.1.1",
36
+
"@atcute/lexicon-resolver": "^0.1.0",
36
37
"@atcute/lexicons": "^1.1.1",
37
38
"@atcute/oauth-browser-client": "^1.0.26",
38
39
"@atcute/tangled": "^1.0.6",
39
40
"@atcute/tid": "^1.0.2",
40
41
"@atcute/uint8array": "^1.0.4",
41
-
"@codemirror/commands": "^6.8.1",
42
+
"@codemirror/commands": "^6.9.0",
42
43
"@codemirror/lang-json": "^6.0.2",
43
-
"@codemirror/lint": "^6.8.5",
44
+
"@codemirror/lint": "^6.9.0",
44
45
"@codemirror/state": "^6.5.2",
45
-
"@codemirror/view": "^6.38.3",
46
+
"@codemirror/view": "^6.38.4",
46
47
"@fsegurai/codemirror-theme-basic-dark": "^6.2.2",
47
48
"@fsegurai/codemirror-theme-basic-light": "^6.2.2",
48
49
"@mary/exif-rm": "jsr:^0.2.2",
···
52
53
"codemirror": "^6.0.2",
53
54
"solid-js": "^1.9.9"
54
55
},
55
-
"packageManager": "pnpm@10.12.2+sha512.a32540185b964ee30bb4e979e405adc6af59226b438ee4cc19f9e8773667a66d302f5bfee60a39d3cac69e35e4b96e708a71dd002b7e9359c4112a1722ac323f"
56
+
"packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a"
56
57
}
+273
-250
pnpm-lock.yaml
+273
-250
pnpm-lock.yaml
···
44
44
'@atcute/lexicon-doc':
45
45
specifier: ^1.1.1
46
46
version: 1.1.1
47
+
'@atcute/lexicon-resolver':
48
+
specifier: ^0.1.0
49
+
version: 0.1.0(@atcute/identity-resolver@1.1.3(@atcute/identity@1.1.0))(@atcute/identity@1.1.0)
47
50
'@atcute/lexicons':
48
51
specifier: ^1.1.1
49
52
version: 1.1.1
···
60
63
specifier: ^1.0.4
61
64
version: 1.0.4
62
65
'@codemirror/commands':
63
-
specifier: ^6.8.1
64
-
version: 6.8.1
66
+
specifier: ^6.9.0
67
+
version: 6.9.0
65
68
'@codemirror/lang-json':
66
69
specifier: ^6.0.2
67
70
version: 6.0.2
68
71
'@codemirror/lint':
69
-
specifier: ^6.8.5
70
-
version: 6.8.5
72
+
specifier: ^6.9.0
73
+
version: 6.9.0
71
74
'@codemirror/state':
72
75
specifier: ^6.5.2
73
76
version: 6.5.2
74
77
'@codemirror/view':
75
-
specifier: ^6.38.3
76
-
version: 6.38.3
78
+
specifier: ^6.38.4
79
+
version: 6.38.4
77
80
'@fsegurai/codemirror-theme-basic-dark':
78
81
specifier: ^6.2.2
79
-
version: 6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.3)(@lezer/highlight@1.2.1)
82
+
version: 6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.4)(@lezer/highlight@1.2.1)
80
83
'@fsegurai/codemirror-theme-basic-light':
81
84
specifier: ^6.2.2
82
-
version: 6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.3)(@lezer/highlight@1.2.1)
85
+
version: 6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.4)(@lezer/highlight@1.2.1)
83
86
'@mary/exif-rm':
84
87
specifier: jsr:^0.2.2
85
88
version: '@jsr/mary__exif-rm@0.2.2'
···
104
107
version: 1.2.68
105
108
'@iconify/tailwind4':
106
109
specifier: ^1.0.6
107
-
version: 1.0.6(tailwindcss@4.1.13)
110
+
version: 1.0.6(tailwindcss@4.1.14)
108
111
'@tailwindcss/vite':
109
-
specifier: ^4.1.13
110
-
version: 4.1.13(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2))
112
+
specifier: ^4.1.14
113
+
version: 4.1.14(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2))
111
114
prettier:
112
115
specifier: ^3.6.2
113
116
version: 3.6.2
114
117
prettier-plugin-organize-imports:
115
118
specifier: ^4.3.0
116
-
version: 4.3.0(prettier@3.6.2)(typescript@5.9.2)
119
+
version: 4.3.0(prettier@3.6.2)(typescript@5.9.3)
117
120
prettier-plugin-tailwindcss:
118
121
specifier: ^0.6.14
119
-
version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2))(prettier@3.6.2)
122
+
version: 0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3))(prettier@3.6.2)
120
123
tailwindcss:
121
-
specifier: ^4.1.13
122
-
version: 4.1.13
124
+
specifier: ^4.1.14
125
+
version: 4.1.14
123
126
typescript:
124
-
specifier: ^5.9.2
125
-
version: 5.9.2
127
+
specifier: ^5.9.3
128
+
version: 5.9.3
126
129
vite:
127
-
specifier: ^7.1.7
128
-
version: 7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)
130
+
specifier: ^7.1.8
131
+
version: 7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)
129
132
vite-plugin-solid:
130
-
specifier: ^2.11.8
131
-
version: 2.11.8(solid-js@1.9.9)(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2))
133
+
specifier: ^2.11.9
134
+
version: 2.11.9(solid-js@1.9.9)(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2))
132
135
133
136
packages:
134
137
···
175
178
176
179
'@atcute/lexicon-doc@1.1.1':
177
180
resolution: {integrity: sha512-/6M4K34ICZWa9rRiM9YWSsDZs0Vjv05SFJBb03mD+x14W01gIVLPK2UXiP0yIodgzWHhPQ79LLdyMJ8LirC84w==}
181
+
182
+
'@atcute/lexicon-resolver@0.1.0':
183
+
resolution: {integrity: sha512-j63pB+PcxQX+hSIOqb4Lorlavv3yjUncgElPHdq3mUeKjZNJbpRZu5uZ0kdcP76sVjoyl52LyS5E2OSGKbK2Zg==}
184
+
peerDependencies:
185
+
'@atcute/identity': ^1.1.0
186
+
'@atcute/identity-resolver': ^1.1.3
178
187
179
188
'@atcute/lexicons@1.1.1':
180
189
resolution: {integrity: sha512-k6qy5p3j9fJJ6ekaMPfEfp3ni4TW/XNuH9ZmsuwC0fi0tOjp+Fa8ZQakHwnqOzFt/cVBfGcmYE/lKNAbeTjgUg==}
···
285
294
resolution: {integrity: sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==}
286
295
engines: {node: '>= 18'}
287
296
288
-
'@codemirror/autocomplete@6.18.7':
289
-
resolution: {integrity: sha512-8EzdeIoWPJDsMBwz3zdzwXnUpCzMiCyz5/A3FIPpriaclFCGDkAzK13sMcnsu5rowqiyeQN2Vs2TsOcoDPZirQ==}
297
+
'@codemirror/autocomplete@6.19.0':
298
+
resolution: {integrity: sha512-61Hfv3cF07XvUxNeC3E7jhG8XNi1Yom1G0lRC936oLnlF+jrbrv8rc/J98XlYzcsAoTVupfsf5fLej1aI8kyIg==}
290
299
291
-
'@codemirror/commands@6.8.1':
292
-
resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==}
300
+
'@codemirror/commands@6.9.0':
301
+
resolution: {integrity: sha512-454TVgjhO6cMufsyyGN70rGIfJxJEjcqjBG2x2Y03Y/+Fm99d3O/Kv1QDYWuG6hvxsgmjXmBuATikIIYvERX+w==}
293
302
294
303
'@codemirror/lang-json@6.0.2':
295
304
resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==}
···
297
306
'@codemirror/language@6.11.3':
298
307
resolution: {integrity: sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==}
299
308
300
-
'@codemirror/lint@6.8.5':
301
-
resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==}
309
+
'@codemirror/lint@6.9.0':
310
+
resolution: {integrity: sha512-wZxW+9XDytH3SKvS8cQzMyQCaaazH8XL1EMHleHe00wVzsv7NBQKVW2yzEHrRhmM7ZOhVdItPbvlRBvMp9ej7A==}
302
311
303
312
'@codemirror/search@6.5.11':
304
313
resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==}
···
306
315
'@codemirror/state@6.5.2':
307
316
resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==}
308
317
309
-
'@codemirror/view@6.38.3':
310
-
resolution: {integrity: sha512-x2t87+oqwB1mduiQZ6huIghjMt4uZKFEdj66IcXw7+a5iBEvv9lh7EWDRHI7crnD4BMGpnyq/RzmCGbiEZLcvQ==}
318
+
'@codemirror/view@6.38.4':
319
+
resolution: {integrity: sha512-hduz0suCcUSC/kM8Fq3A9iLwInJDl8fD1xLpTIk+5xkNm8z/FT7UsIa9sOXrkpChh+XXc18RzswE8QqELsVl+g==}
311
320
312
321
'@esbuild/aix-ppc64@0.23.1':
313
322
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
···
680
689
'@noble/secp256k1@2.3.0':
681
690
resolution: {integrity: sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw==}
682
691
683
-
'@rollup/rollup-android-arm-eabi@4.52.2':
684
-
resolution: {integrity: sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==}
692
+
'@rollup/rollup-android-arm-eabi@4.52.3':
693
+
resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==}
685
694
cpu: [arm]
686
695
os: [android]
687
696
688
-
'@rollup/rollup-android-arm64@4.52.2':
689
-
resolution: {integrity: sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==}
697
+
'@rollup/rollup-android-arm64@4.52.3':
698
+
resolution: {integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==}
690
699
cpu: [arm64]
691
700
os: [android]
692
701
693
-
'@rollup/rollup-darwin-arm64@4.52.2':
694
-
resolution: {integrity: sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==}
702
+
'@rollup/rollup-darwin-arm64@4.52.3':
703
+
resolution: {integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==}
695
704
cpu: [arm64]
696
705
os: [darwin]
697
706
698
-
'@rollup/rollup-darwin-x64@4.52.2':
699
-
resolution: {integrity: sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==}
707
+
'@rollup/rollup-darwin-x64@4.52.3':
708
+
resolution: {integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==}
700
709
cpu: [x64]
701
710
os: [darwin]
702
711
703
-
'@rollup/rollup-freebsd-arm64@4.52.2':
704
-
resolution: {integrity: sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==}
712
+
'@rollup/rollup-freebsd-arm64@4.52.3':
713
+
resolution: {integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==}
705
714
cpu: [arm64]
706
715
os: [freebsd]
707
716
708
-
'@rollup/rollup-freebsd-x64@4.52.2':
709
-
resolution: {integrity: sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==}
717
+
'@rollup/rollup-freebsd-x64@4.52.3':
718
+
resolution: {integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==}
710
719
cpu: [x64]
711
720
os: [freebsd]
712
721
713
-
'@rollup/rollup-linux-arm-gnueabihf@4.52.2':
714
-
resolution: {integrity: sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==}
722
+
'@rollup/rollup-linux-arm-gnueabihf@4.52.3':
723
+
resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==}
715
724
cpu: [arm]
716
725
os: [linux]
717
726
718
-
'@rollup/rollup-linux-arm-musleabihf@4.52.2':
719
-
resolution: {integrity: sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==}
727
+
'@rollup/rollup-linux-arm-musleabihf@4.52.3':
728
+
resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==}
720
729
cpu: [arm]
721
730
os: [linux]
722
731
723
-
'@rollup/rollup-linux-arm64-gnu@4.52.2':
724
-
resolution: {integrity: sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==}
732
+
'@rollup/rollup-linux-arm64-gnu@4.52.3':
733
+
resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==}
725
734
cpu: [arm64]
726
735
os: [linux]
727
736
728
-
'@rollup/rollup-linux-arm64-musl@4.52.2':
729
-
resolution: {integrity: sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==}
737
+
'@rollup/rollup-linux-arm64-musl@4.52.3':
738
+
resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==}
730
739
cpu: [arm64]
731
740
os: [linux]
732
741
733
-
'@rollup/rollup-linux-loong64-gnu@4.52.2':
734
-
resolution: {integrity: sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==}
742
+
'@rollup/rollup-linux-loong64-gnu@4.52.3':
743
+
resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==}
735
744
cpu: [loong64]
736
745
os: [linux]
737
746
738
-
'@rollup/rollup-linux-ppc64-gnu@4.52.2':
739
-
resolution: {integrity: sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==}
747
+
'@rollup/rollup-linux-ppc64-gnu@4.52.3':
748
+
resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==}
740
749
cpu: [ppc64]
741
750
os: [linux]
742
751
743
-
'@rollup/rollup-linux-riscv64-gnu@4.52.2':
744
-
resolution: {integrity: sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==}
752
+
'@rollup/rollup-linux-riscv64-gnu@4.52.3':
753
+
resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==}
745
754
cpu: [riscv64]
746
755
os: [linux]
747
756
748
-
'@rollup/rollup-linux-riscv64-musl@4.52.2':
749
-
resolution: {integrity: sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==}
757
+
'@rollup/rollup-linux-riscv64-musl@4.52.3':
758
+
resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==}
750
759
cpu: [riscv64]
751
760
os: [linux]
752
761
753
-
'@rollup/rollup-linux-s390x-gnu@4.52.2':
754
-
resolution: {integrity: sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==}
762
+
'@rollup/rollup-linux-s390x-gnu@4.52.3':
763
+
resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==}
755
764
cpu: [s390x]
756
765
os: [linux]
757
766
758
-
'@rollup/rollup-linux-x64-gnu@4.52.2':
759
-
resolution: {integrity: sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==}
767
+
'@rollup/rollup-linux-x64-gnu@4.52.3':
768
+
resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==}
760
769
cpu: [x64]
761
770
os: [linux]
762
771
763
-
'@rollup/rollup-linux-x64-musl@4.52.2':
764
-
resolution: {integrity: sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==}
772
+
'@rollup/rollup-linux-x64-musl@4.52.3':
773
+
resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==}
765
774
cpu: [x64]
766
775
os: [linux]
767
776
768
-
'@rollup/rollup-openharmony-arm64@4.52.2':
769
-
resolution: {integrity: sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==}
777
+
'@rollup/rollup-openharmony-arm64@4.52.3':
778
+
resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==}
770
779
cpu: [arm64]
771
780
os: [openharmony]
772
781
773
-
'@rollup/rollup-win32-arm64-msvc@4.52.2':
774
-
resolution: {integrity: sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==}
782
+
'@rollup/rollup-win32-arm64-msvc@4.52.3':
783
+
resolution: {integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==}
775
784
cpu: [arm64]
776
785
os: [win32]
777
786
778
-
'@rollup/rollup-win32-ia32-msvc@4.52.2':
779
-
resolution: {integrity: sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==}
787
+
'@rollup/rollup-win32-ia32-msvc@4.52.3':
788
+
resolution: {integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==}
780
789
cpu: [ia32]
781
790
os: [win32]
782
791
783
-
'@rollup/rollup-win32-x64-gnu@4.52.2':
784
-
resolution: {integrity: sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==}
792
+
'@rollup/rollup-win32-x64-gnu@4.52.3':
793
+
resolution: {integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==}
785
794
cpu: [x64]
786
795
os: [win32]
787
796
788
-
'@rollup/rollup-win32-x64-msvc@4.52.2':
789
-
resolution: {integrity: sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==}
797
+
'@rollup/rollup-win32-x64-msvc@4.52.3':
798
+
resolution: {integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==}
790
799
cpu: [x64]
791
800
os: [win32]
792
801
···
803
812
peerDependencies:
804
813
solid-js: ^1.8.6
805
814
806
-
'@tailwindcss/node@4.1.13':
807
-
resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==}
815
+
'@tailwindcss/node@4.1.14':
816
+
resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==}
808
817
809
-
'@tailwindcss/oxide-android-arm64@4.1.13':
810
-
resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==}
818
+
'@tailwindcss/oxide-android-arm64@4.1.14':
819
+
resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==}
811
820
engines: {node: '>= 10'}
812
821
cpu: [arm64]
813
822
os: [android]
814
823
815
-
'@tailwindcss/oxide-darwin-arm64@4.1.13':
816
-
resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==}
824
+
'@tailwindcss/oxide-darwin-arm64@4.1.14':
825
+
resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==}
817
826
engines: {node: '>= 10'}
818
827
cpu: [arm64]
819
828
os: [darwin]
820
829
821
-
'@tailwindcss/oxide-darwin-x64@4.1.13':
822
-
resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==}
830
+
'@tailwindcss/oxide-darwin-x64@4.1.14':
831
+
resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==}
823
832
engines: {node: '>= 10'}
824
833
cpu: [x64]
825
834
os: [darwin]
826
835
827
-
'@tailwindcss/oxide-freebsd-x64@4.1.13':
828
-
resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==}
836
+
'@tailwindcss/oxide-freebsd-x64@4.1.14':
837
+
resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==}
829
838
engines: {node: '>= 10'}
830
839
cpu: [x64]
831
840
os: [freebsd]
832
841
833
-
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
834
-
resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==}
842
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
843
+
resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==}
835
844
engines: {node: '>= 10'}
836
845
cpu: [arm]
837
846
os: [linux]
838
847
839
-
'@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
840
-
resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==}
848
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
849
+
resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==}
841
850
engines: {node: '>= 10'}
842
851
cpu: [arm64]
843
852
os: [linux]
844
853
845
-
'@tailwindcss/oxide-linux-arm64-musl@4.1.13':
846
-
resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==}
854
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.14':
855
+
resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==}
847
856
engines: {node: '>= 10'}
848
857
cpu: [arm64]
849
858
os: [linux]
850
859
851
-
'@tailwindcss/oxide-linux-x64-gnu@4.1.13':
852
-
resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==}
860
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.14':
861
+
resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==}
853
862
engines: {node: '>= 10'}
854
863
cpu: [x64]
855
864
os: [linux]
856
865
857
-
'@tailwindcss/oxide-linux-x64-musl@4.1.13':
858
-
resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==}
866
+
'@tailwindcss/oxide-linux-x64-musl@4.1.14':
867
+
resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==}
859
868
engines: {node: '>= 10'}
860
869
cpu: [x64]
861
870
os: [linux]
862
871
863
-
'@tailwindcss/oxide-wasm32-wasi@4.1.13':
864
-
resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==}
872
+
'@tailwindcss/oxide-wasm32-wasi@4.1.14':
873
+
resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==}
865
874
engines: {node: '>=14.0.0'}
866
875
cpu: [wasm32]
867
876
bundledDependencies:
···
872
881
- '@emnapi/wasi-threads'
873
882
- tslib
874
883
875
-
'@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
876
-
resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==}
884
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.14':
885
+
resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==}
877
886
engines: {node: '>= 10'}
878
887
cpu: [arm64]
879
888
os: [win32]
880
889
881
-
'@tailwindcss/oxide-win32-x64-msvc@4.1.13':
882
-
resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==}
890
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.14':
891
+
resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==}
883
892
engines: {node: '>= 10'}
884
893
cpu: [x64]
885
894
os: [win32]
886
895
887
-
'@tailwindcss/oxide@4.1.13':
888
-
resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==}
896
+
'@tailwindcss/oxide@4.1.14':
897
+
resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==}
889
898
engines: {node: '>= 10'}
890
899
891
-
'@tailwindcss/vite@4.1.13':
892
-
resolution: {integrity: sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==}
900
+
'@tailwindcss/vite@4.1.14':
901
+
resolution: {integrity: sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==}
893
902
peerDependencies:
894
903
vite: ^5.2.0 || ^6 || ^7
895
904
···
930
939
solid-js:
931
940
optional: true
932
941
933
-
baseline-browser-mapping@2.8.6:
934
-
resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==}
942
+
baseline-browser-mapping@2.8.10:
943
+
resolution: {integrity: sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==}
935
944
hasBin: true
936
945
937
-
browserslist@4.26.2:
938
-
resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==}
946
+
browserslist@4.26.3:
947
+
resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==}
939
948
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
940
949
hasBin: true
941
950
942
-
caniuse-lite@1.0.30001745:
943
-
resolution: {integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==}
951
+
caniuse-lite@1.0.30001746:
952
+
resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==}
944
953
945
954
chownr@3.0.0:
946
955
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
···
977
986
resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==}
978
987
engines: {node: '>=8'}
979
988
980
-
electron-to-chromium@1.5.223:
981
-
resolution: {integrity: sha512-qKm55ic6nbEmagFlTFczML33rF90aU+WtrJ9MdTCThrcvDNdUHN4p6QfVN78U06ZmguqXIyMPyYhw2TrbDUwPQ==}
989
+
electron-to-chromium@1.5.228:
990
+
resolution: {integrity: sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==}
982
991
983
992
enhanced-resolve@5.18.3:
984
993
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
···
1043
1052
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
1044
1053
engines: {node: '>=12.13'}
1045
1054
1046
-
jiti@2.6.0:
1047
-
resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==}
1055
+
jiti@2.6.1:
1056
+
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
1048
1057
hasBin: true
1049
1058
1050
1059
js-tokens@4.0.0:
···
1280
1289
resolve-pkg-maps@1.0.0:
1281
1290
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
1282
1291
1283
-
rollup@4.52.2:
1284
-
resolution: {integrity: sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==}
1292
+
rollup@4.52.3:
1293
+
resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==}
1285
1294
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
1286
1295
hasBin: true
1287
1296
···
1314
1323
style-mod@4.1.2:
1315
1324
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
1316
1325
1317
-
tailwindcss@4.1.13:
1318
-
resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==}
1326
+
tailwindcss@4.1.14:
1327
+
resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==}
1319
1328
1320
-
tapable@2.2.3:
1321
-
resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==}
1329
+
tapable@2.3.0:
1330
+
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
1322
1331
engines: {node: '>=6'}
1323
1332
1324
1333
tar@7.5.1:
···
1337
1346
engines: {node: '>=18.0.0'}
1338
1347
hasBin: true
1339
1348
1340
-
typescript@5.9.2:
1341
-
resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
1349
+
typescript@5.9.3:
1350
+
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
1342
1351
engines: {node: '>=14.17'}
1343
1352
hasBin: true
1344
1353
···
1357
1366
validate-html-nesting@1.2.3:
1358
1367
resolution: {integrity: sha512-kdkWdCl6eCeLlRShJKbjVOU2kFKxMF8Ghu50n+crEoyx+VKm3FxAxF9z4DCy6+bbTOqNW0+jcIYRnjoIRzigRw==}
1359
1368
1360
-
vite-plugin-solid@2.11.8:
1361
-
resolution: {integrity: sha512-hFrCxBfv3B1BmFqnJF4JOCYpjrmi/zwyeKjcomQ0khh8HFyQ8SbuBWQ7zGojfrz6HUOBFrJBNySDi/JgAHytWg==}
1369
+
vite-plugin-solid@2.11.9:
1370
+
resolution: {integrity: sha512-bTA6p+bspXZsuulSd2y6aTzegF8xGaJYcq1Uyh/mv+W4DQtzCgL9nN6n2fsTaxp/dMk+ZHHKgGndlNeooqHLKw==}
1362
1371
peerDependencies:
1363
1372
'@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.*
1364
1373
solid-js: ^1.7.2
···
1367
1376
'@testing-library/jest-dom':
1368
1377
optional: true
1369
1378
1370
-
vite@7.1.7:
1371
-
resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==}
1379
+
vite@7.1.8:
1380
+
resolution: {integrity: sha512-oBXvfSHEOL8jF+R9Am7h59Up07kVVGH1NrFGFoEG6bPDZP3tGpQhvkBpy5x7U6+E6wZCu9OihsWgJqDbQIm8LQ==}
1372
1381
engines: {node: ^20.19.0 || >=22.12.0}
1373
1382
hasBin: true
1374
1383
peerDependencies:
···
1509
1518
dependencies:
1510
1519
'@badrap/valita': 0.4.6
1511
1520
1521
+
'@atcute/lexicon-resolver@0.1.0(@atcute/identity-resolver@1.1.3(@atcute/identity@1.1.0))(@atcute/identity@1.1.0)':
1522
+
dependencies:
1523
+
'@atcute/car': 3.1.1
1524
+
'@atcute/cbor': 2.2.5
1525
+
'@atcute/cid': 2.2.3
1526
+
'@atcute/crypto': 2.2.4
1527
+
'@atcute/identity': 1.1.0
1528
+
'@atcute/identity-resolver': 1.1.3(@atcute/identity@1.1.0)
1529
+
'@atcute/lexicon-doc': 1.1.1
1530
+
'@atcute/lexicons': 1.1.1
1531
+
'@atcute/uint8array': 1.0.4
1532
+
'@atcute/util-fetch': 1.0.2
1533
+
'@badrap/valita': 0.4.6
1534
+
1512
1535
'@atcute/lexicons@1.1.1':
1513
1536
dependencies:
1514
1537
esm-env: 1.2.2
···
1581
1604
dependencies:
1582
1605
'@babel/compat-data': 7.28.4
1583
1606
'@babel/helper-validator-option': 7.27.1
1584
-
browserslist: 4.26.2
1607
+
browserslist: 4.26.3
1585
1608
lru-cache: 5.1.1
1586
1609
semver: 6.3.1
1587
1610
···
1654
1677
1655
1678
'@badrap/valita@0.4.6': {}
1656
1679
1657
-
'@codemirror/autocomplete@6.18.7':
1680
+
'@codemirror/autocomplete@6.19.0':
1658
1681
dependencies:
1659
1682
'@codemirror/language': 6.11.3
1660
1683
'@codemirror/state': 6.5.2
1661
-
'@codemirror/view': 6.38.3
1684
+
'@codemirror/view': 6.38.4
1662
1685
'@lezer/common': 1.2.3
1663
1686
1664
-
'@codemirror/commands@6.8.1':
1687
+
'@codemirror/commands@6.9.0':
1665
1688
dependencies:
1666
1689
'@codemirror/language': 6.11.3
1667
1690
'@codemirror/state': 6.5.2
1668
-
'@codemirror/view': 6.38.3
1691
+
'@codemirror/view': 6.38.4
1669
1692
'@lezer/common': 1.2.3
1670
1693
1671
1694
'@codemirror/lang-json@6.0.2':
···
1676
1699
'@codemirror/language@6.11.3':
1677
1700
dependencies:
1678
1701
'@codemirror/state': 6.5.2
1679
-
'@codemirror/view': 6.38.3
1702
+
'@codemirror/view': 6.38.4
1680
1703
'@lezer/common': 1.2.3
1681
1704
'@lezer/highlight': 1.2.1
1682
1705
'@lezer/lr': 1.4.2
1683
1706
style-mod: 4.1.2
1684
1707
1685
-
'@codemirror/lint@6.8.5':
1708
+
'@codemirror/lint@6.9.0':
1686
1709
dependencies:
1687
1710
'@codemirror/state': 6.5.2
1688
-
'@codemirror/view': 6.38.3
1711
+
'@codemirror/view': 6.38.4
1689
1712
crelt: 1.0.6
1690
1713
1691
1714
'@codemirror/search@6.5.11':
1692
1715
dependencies:
1693
1716
'@codemirror/state': 6.5.2
1694
-
'@codemirror/view': 6.38.3
1717
+
'@codemirror/view': 6.38.4
1695
1718
crelt: 1.0.6
1696
1719
1697
1720
'@codemirror/state@6.5.2':
1698
1721
dependencies:
1699
1722
'@marijn/find-cluster-break': 1.0.2
1700
1723
1701
-
'@codemirror/view@6.38.3':
1724
+
'@codemirror/view@6.38.4':
1702
1725
dependencies:
1703
1726
'@codemirror/state': 6.5.2
1704
1727
crelt: 1.0.6
···
1855
1878
'@esbuild/win32-x64@0.25.10':
1856
1879
optional: true
1857
1880
1858
-
'@fsegurai/codemirror-theme-basic-dark@6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.3)(@lezer/highlight@1.2.1)':
1881
+
'@fsegurai/codemirror-theme-basic-dark@6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.4)(@lezer/highlight@1.2.1)':
1859
1882
dependencies:
1860
1883
'@codemirror/language': 6.11.3
1861
1884
'@codemirror/state': 6.5.2
1862
-
'@codemirror/view': 6.38.3
1885
+
'@codemirror/view': 6.38.4
1863
1886
'@lezer/highlight': 1.2.1
1864
1887
1865
-
'@fsegurai/codemirror-theme-basic-light@6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.3)(@lezer/highlight@1.2.1)':
1888
+
'@fsegurai/codemirror-theme-basic-light@6.2.2(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.4)(@lezer/highlight@1.2.1)':
1866
1889
dependencies:
1867
1890
'@codemirror/language': 6.11.3
1868
1891
'@codemirror/state': 6.5.2
1869
-
'@codemirror/view': 6.38.3
1892
+
'@codemirror/view': 6.38.4
1870
1893
'@lezer/highlight': 1.2.1
1871
1894
1872
1895
'@iconify-json/lucide@1.2.68':
1873
1896
dependencies:
1874
1897
'@iconify/types': 2.0.0
1875
1898
1876
-
'@iconify/tailwind4@1.0.6(tailwindcss@4.1.13)':
1899
+
'@iconify/tailwind4@1.0.6(tailwindcss@4.1.14)':
1877
1900
dependencies:
1878
1901
'@iconify/types': 2.0.0
1879
1902
'@iconify/utils': 2.3.0
1880
-
tailwindcss: 4.1.13
1903
+
tailwindcss: 4.1.14
1881
1904
transitivePeerDependencies:
1882
1905
- supports-color
1883
1906
···
1941
1964
1942
1965
'@noble/secp256k1@2.3.0': {}
1943
1966
1944
-
'@rollup/rollup-android-arm-eabi@4.52.2':
1967
+
'@rollup/rollup-android-arm-eabi@4.52.3':
1945
1968
optional: true
1946
1969
1947
-
'@rollup/rollup-android-arm64@4.52.2':
1970
+
'@rollup/rollup-android-arm64@4.52.3':
1948
1971
optional: true
1949
1972
1950
-
'@rollup/rollup-darwin-arm64@4.52.2':
1973
+
'@rollup/rollup-darwin-arm64@4.52.3':
1951
1974
optional: true
1952
1975
1953
-
'@rollup/rollup-darwin-x64@4.52.2':
1976
+
'@rollup/rollup-darwin-x64@4.52.3':
1954
1977
optional: true
1955
1978
1956
-
'@rollup/rollup-freebsd-arm64@4.52.2':
1979
+
'@rollup/rollup-freebsd-arm64@4.52.3':
1957
1980
optional: true
1958
1981
1959
-
'@rollup/rollup-freebsd-x64@4.52.2':
1982
+
'@rollup/rollup-freebsd-x64@4.52.3':
1960
1983
optional: true
1961
1984
1962
-
'@rollup/rollup-linux-arm-gnueabihf@4.52.2':
1985
+
'@rollup/rollup-linux-arm-gnueabihf@4.52.3':
1963
1986
optional: true
1964
1987
1965
-
'@rollup/rollup-linux-arm-musleabihf@4.52.2':
1988
+
'@rollup/rollup-linux-arm-musleabihf@4.52.3':
1966
1989
optional: true
1967
1990
1968
-
'@rollup/rollup-linux-arm64-gnu@4.52.2':
1991
+
'@rollup/rollup-linux-arm64-gnu@4.52.3':
1969
1992
optional: true
1970
1993
1971
-
'@rollup/rollup-linux-arm64-musl@4.52.2':
1994
+
'@rollup/rollup-linux-arm64-musl@4.52.3':
1972
1995
optional: true
1973
1996
1974
-
'@rollup/rollup-linux-loong64-gnu@4.52.2':
1997
+
'@rollup/rollup-linux-loong64-gnu@4.52.3':
1975
1998
optional: true
1976
1999
1977
-
'@rollup/rollup-linux-ppc64-gnu@4.52.2':
2000
+
'@rollup/rollup-linux-ppc64-gnu@4.52.3':
1978
2001
optional: true
1979
2002
1980
-
'@rollup/rollup-linux-riscv64-gnu@4.52.2':
2003
+
'@rollup/rollup-linux-riscv64-gnu@4.52.3':
1981
2004
optional: true
1982
2005
1983
-
'@rollup/rollup-linux-riscv64-musl@4.52.2':
2006
+
'@rollup/rollup-linux-riscv64-musl@4.52.3':
1984
2007
optional: true
1985
2008
1986
-
'@rollup/rollup-linux-s390x-gnu@4.52.2':
2009
+
'@rollup/rollup-linux-s390x-gnu@4.52.3':
1987
2010
optional: true
1988
2011
1989
-
'@rollup/rollup-linux-x64-gnu@4.52.2':
2012
+
'@rollup/rollup-linux-x64-gnu@4.52.3':
1990
2013
optional: true
1991
2014
1992
-
'@rollup/rollup-linux-x64-musl@4.52.2':
2015
+
'@rollup/rollup-linux-x64-musl@4.52.3':
1993
2016
optional: true
1994
2017
1995
-
'@rollup/rollup-openharmony-arm64@4.52.2':
2018
+
'@rollup/rollup-openharmony-arm64@4.52.3':
1996
2019
optional: true
1997
2020
1998
-
'@rollup/rollup-win32-arm64-msvc@4.52.2':
2021
+
'@rollup/rollup-win32-arm64-msvc@4.52.3':
1999
2022
optional: true
2000
2023
2001
-
'@rollup/rollup-win32-ia32-msvc@4.52.2':
2024
+
'@rollup/rollup-win32-ia32-msvc@4.52.3':
2002
2025
optional: true
2003
2026
2004
-
'@rollup/rollup-win32-x64-gnu@4.52.2':
2027
+
'@rollup/rollup-win32-x64-gnu@4.52.3':
2005
2028
optional: true
2006
2029
2007
-
'@rollup/rollup-win32-x64-msvc@4.52.2':
2030
+
'@rollup/rollup-win32-x64-msvc@4.52.3':
2008
2031
optional: true
2009
2032
2010
2033
'@skyware/firehose@0.5.2':
···
2021
2044
dependencies:
2022
2045
solid-js: 1.9.9
2023
2046
2024
-
'@tailwindcss/node@4.1.13':
2047
+
'@tailwindcss/node@4.1.14':
2025
2048
dependencies:
2026
2049
'@jridgewell/remapping': 2.3.5
2027
2050
enhanced-resolve: 5.18.3
2028
-
jiti: 2.6.0
2051
+
jiti: 2.6.1
2029
2052
lightningcss: 1.30.1
2030
2053
magic-string: 0.30.19
2031
2054
source-map-js: 1.2.1
2032
-
tailwindcss: 4.1.13
2055
+
tailwindcss: 4.1.14
2033
2056
2034
-
'@tailwindcss/oxide-android-arm64@4.1.13':
2057
+
'@tailwindcss/oxide-android-arm64@4.1.14':
2035
2058
optional: true
2036
2059
2037
-
'@tailwindcss/oxide-darwin-arm64@4.1.13':
2060
+
'@tailwindcss/oxide-darwin-arm64@4.1.14':
2038
2061
optional: true
2039
2062
2040
-
'@tailwindcss/oxide-darwin-x64@4.1.13':
2063
+
'@tailwindcss/oxide-darwin-x64@4.1.14':
2041
2064
optional: true
2042
2065
2043
-
'@tailwindcss/oxide-freebsd-x64@4.1.13':
2066
+
'@tailwindcss/oxide-freebsd-x64@4.1.14':
2044
2067
optional: true
2045
2068
2046
-
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
2069
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
2047
2070
optional: true
2048
2071
2049
-
'@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
2072
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
2050
2073
optional: true
2051
2074
2052
-
'@tailwindcss/oxide-linux-arm64-musl@4.1.13':
2075
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.14':
2053
2076
optional: true
2054
2077
2055
-
'@tailwindcss/oxide-linux-x64-gnu@4.1.13':
2078
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.14':
2056
2079
optional: true
2057
2080
2058
-
'@tailwindcss/oxide-linux-x64-musl@4.1.13':
2081
+
'@tailwindcss/oxide-linux-x64-musl@4.1.14':
2059
2082
optional: true
2060
2083
2061
-
'@tailwindcss/oxide-wasm32-wasi@4.1.13':
2084
+
'@tailwindcss/oxide-wasm32-wasi@4.1.14':
2062
2085
optional: true
2063
2086
2064
-
'@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
2087
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.14':
2065
2088
optional: true
2066
2089
2067
-
'@tailwindcss/oxide-win32-x64-msvc@4.1.13':
2090
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.14':
2068
2091
optional: true
2069
2092
2070
-
'@tailwindcss/oxide@4.1.13':
2093
+
'@tailwindcss/oxide@4.1.14':
2071
2094
dependencies:
2072
2095
detect-libc: 2.1.1
2073
2096
tar: 7.5.1
2074
2097
optionalDependencies:
2075
-
'@tailwindcss/oxide-android-arm64': 4.1.13
2076
-
'@tailwindcss/oxide-darwin-arm64': 4.1.13
2077
-
'@tailwindcss/oxide-darwin-x64': 4.1.13
2078
-
'@tailwindcss/oxide-freebsd-x64': 4.1.13
2079
-
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13
2080
-
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.13
2081
-
'@tailwindcss/oxide-linux-arm64-musl': 4.1.13
2082
-
'@tailwindcss/oxide-linux-x64-gnu': 4.1.13
2083
-
'@tailwindcss/oxide-linux-x64-musl': 4.1.13
2084
-
'@tailwindcss/oxide-wasm32-wasi': 4.1.13
2085
-
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.13
2086
-
'@tailwindcss/oxide-win32-x64-msvc': 4.1.13
2098
+
'@tailwindcss/oxide-android-arm64': 4.1.14
2099
+
'@tailwindcss/oxide-darwin-arm64': 4.1.14
2100
+
'@tailwindcss/oxide-darwin-x64': 4.1.14
2101
+
'@tailwindcss/oxide-freebsd-x64': 4.1.14
2102
+
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14
2103
+
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.14
2104
+
'@tailwindcss/oxide-linux-arm64-musl': 4.1.14
2105
+
'@tailwindcss/oxide-linux-x64-gnu': 4.1.14
2106
+
'@tailwindcss/oxide-linux-x64-musl': 4.1.14
2107
+
'@tailwindcss/oxide-wasm32-wasi': 4.1.14
2108
+
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.14
2109
+
'@tailwindcss/oxide-win32-x64-msvc': 4.1.14
2087
2110
2088
-
'@tailwindcss/vite@4.1.13(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2))':
2111
+
'@tailwindcss/vite@4.1.14(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2))':
2089
2112
dependencies:
2090
-
'@tailwindcss/node': 4.1.13
2091
-
'@tailwindcss/oxide': 4.1.13
2092
-
tailwindcss: 4.1.13
2093
-
vite: 7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)
2113
+
'@tailwindcss/node': 4.1.14
2114
+
'@tailwindcss/oxide': 4.1.14
2115
+
tailwindcss: 4.1.14
2116
+
vite: 7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)
2094
2117
2095
2118
'@types/babel__core@7.20.5':
2096
2119
dependencies:
···
2139
2162
optionalDependencies:
2140
2163
solid-js: 1.9.9
2141
2164
2142
-
baseline-browser-mapping@2.8.6: {}
2165
+
baseline-browser-mapping@2.8.10: {}
2143
2166
2144
-
browserslist@4.26.2:
2167
+
browserslist@4.26.3:
2145
2168
dependencies:
2146
-
baseline-browser-mapping: 2.8.6
2147
-
caniuse-lite: 1.0.30001745
2148
-
electron-to-chromium: 1.5.223
2169
+
baseline-browser-mapping: 2.8.10
2170
+
caniuse-lite: 1.0.30001746
2171
+
electron-to-chromium: 1.5.228
2149
2172
node-releases: 2.0.21
2150
-
update-browserslist-db: 1.1.3(browserslist@4.26.2)
2173
+
update-browserslist-db: 1.1.3(browserslist@4.26.3)
2151
2174
2152
-
caniuse-lite@1.0.30001745: {}
2175
+
caniuse-lite@1.0.30001746: {}
2153
2176
2154
2177
chownr@3.0.0: {}
2155
2178
2156
2179
codemirror@6.0.2:
2157
2180
dependencies:
2158
-
'@codemirror/autocomplete': 6.18.7
2159
-
'@codemirror/commands': 6.8.1
2181
+
'@codemirror/autocomplete': 6.19.0
2182
+
'@codemirror/commands': 6.9.0
2160
2183
'@codemirror/language': 6.11.3
2161
-
'@codemirror/lint': 6.8.5
2184
+
'@codemirror/lint': 6.9.0
2162
2185
'@codemirror/search': 6.5.11
2163
2186
'@codemirror/state': 6.5.2
2164
-
'@codemirror/view': 6.38.3
2187
+
'@codemirror/view': 6.38.4
2165
2188
2166
2189
confbox@0.1.8: {}
2167
2190
···
2179
2202
2180
2203
detect-libc@2.1.1: {}
2181
2204
2182
-
electron-to-chromium@1.5.223: {}
2205
+
electron-to-chromium@1.5.228: {}
2183
2206
2184
2207
enhanced-resolve@5.18.3:
2185
2208
dependencies:
2186
2209
graceful-fs: 4.2.11
2187
-
tapable: 2.2.3
2210
+
tapable: 2.3.0
2188
2211
2189
2212
entities@6.0.1: {}
2190
2213
···
2273
2296
2274
2297
is-what@4.1.16: {}
2275
2298
2276
-
jiti@2.6.0: {}
2299
+
jiti@2.6.1: {}
2277
2300
2278
2301
js-tokens@4.0.0: {}
2279
2302
···
2399
2422
picocolors: 1.1.1
2400
2423
source-map-js: 1.2.1
2401
2424
2402
-
prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2):
2425
+
prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3):
2403
2426
dependencies:
2404
2427
prettier: 3.6.2
2405
-
typescript: 5.9.2
2428
+
typescript: 5.9.3
2406
2429
2407
-
prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.2))(prettier@3.6.2):
2430
+
prettier-plugin-tailwindcss@0.6.14(prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3))(prettier@3.6.2):
2408
2431
dependencies:
2409
2432
prettier: 3.6.2
2410
2433
optionalDependencies:
2411
-
prettier-plugin-organize-imports: 4.3.0(prettier@3.6.2)(typescript@5.9.2)
2434
+
prettier-plugin-organize-imports: 4.3.0(prettier@3.6.2)(typescript@5.9.3)
2412
2435
2413
2436
prettier@3.6.2: {}
2414
2437
···
2417
2440
resolve-pkg-maps@1.0.0:
2418
2441
optional: true
2419
2442
2420
-
rollup@4.52.2:
2443
+
rollup@4.52.3:
2421
2444
dependencies:
2422
2445
'@types/estree': 1.0.8
2423
2446
optionalDependencies:
2424
-
'@rollup/rollup-android-arm-eabi': 4.52.2
2425
-
'@rollup/rollup-android-arm64': 4.52.2
2426
-
'@rollup/rollup-darwin-arm64': 4.52.2
2427
-
'@rollup/rollup-darwin-x64': 4.52.2
2428
-
'@rollup/rollup-freebsd-arm64': 4.52.2
2429
-
'@rollup/rollup-freebsd-x64': 4.52.2
2430
-
'@rollup/rollup-linux-arm-gnueabihf': 4.52.2
2431
-
'@rollup/rollup-linux-arm-musleabihf': 4.52.2
2432
-
'@rollup/rollup-linux-arm64-gnu': 4.52.2
2433
-
'@rollup/rollup-linux-arm64-musl': 4.52.2
2434
-
'@rollup/rollup-linux-loong64-gnu': 4.52.2
2435
-
'@rollup/rollup-linux-ppc64-gnu': 4.52.2
2436
-
'@rollup/rollup-linux-riscv64-gnu': 4.52.2
2437
-
'@rollup/rollup-linux-riscv64-musl': 4.52.2
2438
-
'@rollup/rollup-linux-s390x-gnu': 4.52.2
2439
-
'@rollup/rollup-linux-x64-gnu': 4.52.2
2440
-
'@rollup/rollup-linux-x64-musl': 4.52.2
2441
-
'@rollup/rollup-openharmony-arm64': 4.52.2
2442
-
'@rollup/rollup-win32-arm64-msvc': 4.52.2
2443
-
'@rollup/rollup-win32-ia32-msvc': 4.52.2
2444
-
'@rollup/rollup-win32-x64-gnu': 4.52.2
2445
-
'@rollup/rollup-win32-x64-msvc': 4.52.2
2447
+
'@rollup/rollup-android-arm-eabi': 4.52.3
2448
+
'@rollup/rollup-android-arm64': 4.52.3
2449
+
'@rollup/rollup-darwin-arm64': 4.52.3
2450
+
'@rollup/rollup-darwin-x64': 4.52.3
2451
+
'@rollup/rollup-freebsd-arm64': 4.52.3
2452
+
'@rollup/rollup-freebsd-x64': 4.52.3
2453
+
'@rollup/rollup-linux-arm-gnueabihf': 4.52.3
2454
+
'@rollup/rollup-linux-arm-musleabihf': 4.52.3
2455
+
'@rollup/rollup-linux-arm64-gnu': 4.52.3
2456
+
'@rollup/rollup-linux-arm64-musl': 4.52.3
2457
+
'@rollup/rollup-linux-loong64-gnu': 4.52.3
2458
+
'@rollup/rollup-linux-ppc64-gnu': 4.52.3
2459
+
'@rollup/rollup-linux-riscv64-gnu': 4.52.3
2460
+
'@rollup/rollup-linux-riscv64-musl': 4.52.3
2461
+
'@rollup/rollup-linux-s390x-gnu': 4.52.3
2462
+
'@rollup/rollup-linux-x64-gnu': 4.52.3
2463
+
'@rollup/rollup-linux-x64-musl': 4.52.3
2464
+
'@rollup/rollup-openharmony-arm64': 4.52.3
2465
+
'@rollup/rollup-win32-arm64-msvc': 4.52.3
2466
+
'@rollup/rollup-win32-ia32-msvc': 4.52.3
2467
+
'@rollup/rollup-win32-x64-gnu': 4.52.3
2468
+
'@rollup/rollup-win32-x64-msvc': 4.52.3
2446
2469
fsevents: 2.3.3
2447
2470
2448
2471
semver@6.3.1: {}
···
2472
2495
2473
2496
style-mod@4.1.2: {}
2474
2497
2475
-
tailwindcss@4.1.13: {}
2498
+
tailwindcss@4.1.14: {}
2476
2499
2477
-
tapable@2.2.3: {}
2500
+
tapable@2.3.0: {}
2478
2501
2479
2502
tar@7.5.1:
2480
2503
dependencies:
···
2499
2522
fsevents: 2.3.3
2500
2523
optional: true
2501
2524
2502
-
typescript@5.9.2: {}
2525
+
typescript@5.9.3: {}
2503
2526
2504
2527
ufo@1.6.1: {}
2505
2528
2506
2529
undici-types@6.20.0:
2507
2530
optional: true
2508
2531
2509
-
update-browserslist-db@1.1.3(browserslist@4.26.2):
2532
+
update-browserslist-db@1.1.3(browserslist@4.26.3):
2510
2533
dependencies:
2511
-
browserslist: 4.26.2
2534
+
browserslist: 4.26.3
2512
2535
escalade: 3.2.0
2513
2536
picocolors: 1.1.1
2514
2537
2515
2538
validate-html-nesting@1.2.3: {}
2516
2539
2517
-
vite-plugin-solid@2.11.8(solid-js@1.9.9)(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)):
2540
+
vite-plugin-solid@2.11.9(solid-js@1.9.9)(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)):
2518
2541
dependencies:
2519
2542
'@babel/core': 7.28.4
2520
2543
'@types/babel__core': 7.20.5
···
2522
2545
merge-anything: 5.1.7
2523
2546
solid-js: 1.9.9
2524
2547
solid-refresh: 0.6.3(solid-js@1.9.9)
2525
-
vite: 7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)
2526
-
vitefu: 1.1.1(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2))
2548
+
vite: 7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)
2549
+
vitefu: 1.1.1(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2))
2527
2550
transitivePeerDependencies:
2528
2551
- supports-color
2529
2552
2530
-
vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2):
2553
+
vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2):
2531
2554
dependencies:
2532
2555
esbuild: 0.25.10
2533
2556
fdir: 6.5.0(picomatch@4.0.3)
2534
2557
picomatch: 4.0.3
2535
2558
postcss: 8.5.6
2536
-
rollup: 4.52.2
2559
+
rollup: 4.52.3
2537
2560
tinyglobby: 0.2.15
2538
2561
optionalDependencies:
2539
2562
'@types/node': 22.13.1
2540
2563
fsevents: 2.3.3
2541
-
jiti: 2.6.0
2564
+
jiti: 2.6.1
2542
2565
lightningcss: 1.30.1
2543
2566
tsx: 4.19.2
2544
2567
2545
-
vitefu@1.1.1(vite@7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)):
2568
+
vitefu@1.1.1(vite@7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)):
2546
2569
optionalDependencies:
2547
-
vite: 7.1.7(@types/node@22.13.1)(jiti@2.6.0)(lightningcss@1.30.1)(tsx@4.19.2)
2570
+
vite: 7.1.8(@types/node@22.13.1)(jiti@2.6.1)(lightningcss@1.30.1)(tsx@4.19.2)
2548
2571
2549
2572
w3c-keyname@2.2.8: {}
2550
2573
public/headers/aurora.jpg
public/headers/aurora.jpg
This is a binary file and will not be displayed.
public/headers/forest.jpg
public/headers/forest.jpg
This is a binary file and will not be displayed.
+71
-76
src/components/backlinks.tsx
+71
-76
src/components/backlinks.tsx
···
24
24
const Backlinks = (props: { target: string }) => {
25
25
const fetchBacklinks = async () => {
26
26
const res = await getAllBacklinks(props.target);
27
-
setBacklinks(linksBySource(res.links));
28
-
return res;
27
+
return linksBySource(res.links);
29
28
};
30
29
31
30
const [response] = createResource(fetchBacklinks);
32
-
const [backlinks, setBacklinks] = createSignal<any>();
33
31
34
32
const [show, setShow] = createSignal<{
35
33
collection: string;
···
38
36
} | null>();
39
37
40
38
return (
41
-
<Show when={response()}>
42
-
<div class="flex w-full flex-col gap-1 text-sm wrap-anywhere">
43
-
<For each={backlinks()}>
44
-
{({ collection, path, counts }) => (
39
+
<div class="flex w-full flex-col gap-1 text-sm wrap-anywhere">
40
+
<Show when={response()?.length === 0}>
41
+
<p>No backlinks found.</p>
42
+
</Show>
43
+
<For each={response()}>
44
+
{({ collection, path, counts }) => (
45
+
<div>
45
46
<div>
46
-
<div>
47
-
<div title="Collection containing linking records" class="flex items-center gap-1">
48
-
<span class="iconify lucide--book-text shrink-0"></span>
49
-
{collection}
50
-
</div>
51
-
<div title="Record path where the link is found" class="flex items-center gap-1">
52
-
<span class="iconify lucide--route shrink-0"></span>
53
-
{path.slice(1)}
54
-
</div>
47
+
<div title="Collection containing linking records" class="flex items-center gap-1">
48
+
<span class="iconify lucide--book-text shrink-0"></span>
49
+
{collection}
50
+
</div>
51
+
<div title="Record path where the link is found" class="flex items-center gap-1">
52
+
<span class="iconify lucide--route shrink-0"></span>
53
+
{path.slice(1)}
55
54
</div>
56
-
<div class="ml-4.5">
57
-
<p>
58
-
<button
59
-
class="text-blue-400 hover:underline active:underline"
60
-
title="Show linking records"
61
-
onclick={() =>
62
-
(
63
-
show()?.collection === collection &&
64
-
show()?.path === path &&
65
-
!show()?.showDids
66
-
) ?
67
-
setShow(null)
68
-
: setShow({ collection, path, showDids: false })
69
-
}
70
-
>
71
-
{counts.records} record{counts.records < 2 ? "" : "s"}
72
-
</button>
73
-
{" from "}
74
-
<button
75
-
class="text-blue-400 hover:underline active:underline"
76
-
title="Show linking DIDs"
77
-
onclick={() =>
78
-
(
79
-
show()?.collection === collection &&
80
-
show()?.path === path &&
81
-
show()?.showDids
82
-
) ?
83
-
setShow(null)
84
-
: setShow({ collection, path, showDids: true })
85
-
}
86
-
>
87
-
{counts.distinct_dids} DID
88
-
{counts.distinct_dids < 2 ? "" : "s"}
89
-
</button>
90
-
</p>
91
-
<Show when={show()?.collection === collection && show()?.path === path}>
92
-
<Show when={show()?.showDids}>
93
-
{/* putting this in the `dids` prop directly failed to re-render. idk how to solidjs. */}
94
-
<p class="w-full font-semibold">Distinct identities</p>
95
-
<BacklinkItems
96
-
target={props.target}
97
-
collection={collection}
98
-
path={path}
99
-
dids={true}
100
-
/>
101
-
</Show>
102
-
<Show when={!show()?.showDids}>
103
-
<p class="w-full font-semibold">Records</p>
104
-
<BacklinkItems
105
-
target={props.target}
106
-
collection={collection}
107
-
path={path}
108
-
dids={false}
109
-
/>
110
-
</Show>
55
+
</div>
56
+
<div class="ml-4.5">
57
+
<p>
58
+
<button
59
+
class="text-blue-400 hover:underline active:underline"
60
+
title="Show linking records"
61
+
onclick={() =>
62
+
(
63
+
show()?.collection === collection &&
64
+
show()?.path === path &&
65
+
!show()?.showDids
66
+
) ?
67
+
setShow(null)
68
+
: setShow({ collection, path, showDids: false })
69
+
}
70
+
>
71
+
{counts.records} record{counts.records < 2 ? "" : "s"}
72
+
</button>
73
+
{" from "}
74
+
<button
75
+
class="text-blue-400 hover:underline active:underline"
76
+
title="Show linking DIDs"
77
+
onclick={() =>
78
+
show()?.collection === collection && show()?.path === path && show()?.showDids ?
79
+
setShow(null)
80
+
: setShow({ collection, path, showDids: true })
81
+
}
82
+
>
83
+
{counts.distinct_dids} DID
84
+
{counts.distinct_dids < 2 ? "" : "s"}
85
+
</button>
86
+
</p>
87
+
<Show when={show()?.collection === collection && show()?.path === path}>
88
+
<Show when={show()?.showDids}>
89
+
{/* putting this in the `dids` prop directly failed to re-render. idk how to solidjs. */}
90
+
<p class="w-full font-semibold">Distinct identities</p>
91
+
<BacklinkItems
92
+
target={props.target}
93
+
collection={collection}
94
+
path={path}
95
+
dids={true}
96
+
/>
97
+
</Show>
98
+
<Show when={!show()?.showDids}>
99
+
<p class="w-full font-semibold">Records</p>
100
+
<BacklinkItems
101
+
target={props.target}
102
+
collection={collection}
103
+
path={path}
104
+
dids={false}
105
+
/>
111
106
</Show>
112
-
</div>
107
+
</Show>
113
108
</div>
114
-
)}
115
-
</For>
116
-
</div>
117
-
</Show>
109
+
</div>
110
+
)}
111
+
</For>
112
+
</div>
118
113
);
119
114
};
120
115
+144
-84
src/components/create.tsx
+144
-84
src/components/create.tsx
···
1
1
import { Client } from "@atcute/client";
2
2
import { remove } from "@mary/exif-rm";
3
3
import { useNavigate, useParams } from "@solidjs/router";
4
-
import { createSignal, Show } from "solid-js";
4
+
import { createSignal, onCleanup, Show } from "solid-js";
5
5
import { Editor, editorView } from "../components/editor.jsx";
6
6
import { agent } from "../components/login.jsx";
7
7
import { setNotif } from "../layout.jsx";
···
15
15
const params = useParams();
16
16
const [openDialog, setOpenDialog] = createSignal(false);
17
17
const [notice, setNotice] = createSignal("");
18
-
const [uploading, setUploading] = createSignal(false);
18
+
const [openUpload, setOpenUpload] = createSignal(false);
19
+
let blobInput!: HTMLInputElement;
19
20
let formRef!: HTMLFormElement;
20
21
21
22
const placeholder = () => {
···
125
126
}
126
127
};
127
128
128
-
const uploadBlob = async () => {
129
-
setNotice("");
130
-
let blob: Blob;
129
+
const FileUpload = (props: { file: File }) => {
130
+
const [uploading, setUploading] = createSignal(false);
131
+
const [error, setError] = createSignal("");
131
132
132
-
const file = (document.getElementById("blob") as HTMLInputElement)?.files?.[0];
133
-
if (!file) return;
133
+
onCleanup(() => (blobInput.value = ""));
134
134
135
-
const mimetype = (document.getElementById("mimetype") as HTMLInputElement)?.value;
136
-
(document.getElementById("mimetype") as HTMLInputElement).value = "";
137
-
if (mimetype) blob = new Blob([file], { type: mimetype });
138
-
else blob = file;
135
+
const formatFileSize = (bytes: number) => {
136
+
if (bytes === 0) return "0 Bytes";
137
+
const k = 1024;
138
+
const sizes = ["Bytes", "KB", "MB", "GB"];
139
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
140
+
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
141
+
};
142
+
143
+
const uploadBlob = async () => {
144
+
let blob: Blob;
145
+
146
+
const mimetype = (document.getElementById("mimetype") as HTMLInputElement)?.value;
147
+
(document.getElementById("mimetype") as HTMLInputElement).value = "";
148
+
if (mimetype) blob = new Blob([props.file], { type: mimetype });
149
+
else blob = props.file;
150
+
151
+
if ((document.getElementById("exif-rm") as HTMLInputElement).checked) {
152
+
const exifRemoved = remove(new Uint8Array(await blob.arrayBuffer()));
153
+
if (exifRemoved !== null) blob = new Blob([exifRemoved], { type: blob.type });
154
+
}
139
155
140
-
if ((document.getElementById("exif-rm") as HTMLInputElement).checked) {
141
-
const exifRemoved = remove(new Uint8Array(await blob.arrayBuffer()));
142
-
if (exifRemoved !== null) blob = new Blob([exifRemoved], { type: blob.type });
143
-
}
156
+
const rpc = new Client({ handler: agent()! });
157
+
setUploading(true);
158
+
const res = await rpc.post("com.atproto.repo.uploadBlob", {
159
+
input: blob,
160
+
});
161
+
setUploading(false);
162
+
if (!res.ok) {
163
+
setError(res.data.error);
164
+
return;
165
+
}
166
+
editorView.dispatch({
167
+
changes: {
168
+
from: editorView.state.selection.main.head,
169
+
insert: JSON.stringify(res.data.blob, null, 2),
170
+
},
171
+
});
172
+
setOpenUpload(false);
173
+
};
144
174
145
-
const rpc = new Client({ handler: agent()! });
146
-
setUploading(true);
147
-
const res = await rpc.post("com.atproto.repo.uploadBlob", {
148
-
input: blob,
149
-
});
150
-
setUploading(false);
151
-
(document.getElementById("blob") as HTMLInputElement).value = "";
152
-
if (!res.ok) {
153
-
setNotice(res.data.error);
154
-
return;
155
-
}
156
-
editorView.dispatch({
157
-
changes: {
158
-
from: editorView.state.selection.main.head,
159
-
insert: JSON.stringify(res.data.blob, null, 2),
160
-
},
161
-
});
175
+
return (
176
+
<div class="dark:bg-dark-300 dark:shadow-dark-800 absolute top-70 left-[50%] w-[20rem] -translate-x-1/2 rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 p-4 shadow-md transition-opacity duration-200 dark:border-neutral-700 starting:opacity-0">
177
+
<h2 class="mb-2 font-semibold">Upload blob</h2>
178
+
<div class="flex flex-col gap-2 text-sm">
179
+
<div class="flex flex-col gap-1">
180
+
<p class="flex gap-1">
181
+
<span class="truncate">{props.file.name}</span>
182
+
<span class="shrink-0 text-neutral-600 dark:text-neutral-400">
183
+
({formatFileSize(props.file.size)})
184
+
</span>
185
+
</p>
186
+
</div>
187
+
<div class="flex items-center gap-x-2">
188
+
<label for="mimetype" class="shrink-0 select-none">
189
+
MIME type
190
+
</label>
191
+
<TextInput id="mimetype" placeholder={props.file.type} />
192
+
</div>
193
+
<div class="flex items-center gap-1">
194
+
<input id="exif-rm" type="checkbox" checked />
195
+
<label for="exif-rm" class="select-none">
196
+
Remove EXIF data
197
+
</label>
198
+
</div>
199
+
<p class="text-xs text-neutral-600 dark:text-neutral-400">
200
+
Metadata will be pasted after the cursor
201
+
</p>
202
+
<Show when={error()}>
203
+
<span class="text-red-500 dark:text-red-400">Error: {error()}</span>
204
+
</Show>
205
+
<div class="flex justify-between gap-2">
206
+
<Button onClick={() => setOpenUpload(false)}>Cancel</Button>
207
+
<Show when={uploading()}>
208
+
<div class="flex items-center gap-1">
209
+
<span class="iconify lucide--loader-circle animate-spin"></span>
210
+
<span>Uploading</span>
211
+
</div>
212
+
</Show>
213
+
<Show when={!uploading()}>
214
+
<Button
215
+
onClick={uploadBlob}
216
+
class="dark:shadow-dark-800 flex items-center gap-1 rounded-lg bg-blue-500 px-2 py-1.5 text-xs text-white shadow-xs select-none hover:bg-blue-600 active:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-500 dark:active:bg-blue-400"
217
+
>
218
+
Upload
219
+
</Button>
220
+
</Show>
221
+
</div>
222
+
</div>
223
+
</div>
224
+
);
162
225
};
163
226
164
227
return (
···
172
235
></span>
173
236
<span>{props.create ? "Creating" : "Editing"} record</span>
174
237
</div>
175
-
<button onclick={() => setOpenDialog(false)} class="flex items-center">
176
-
<span class="iconify lucide--x text-lg hover:text-neutral-500 dark:hover:text-neutral-400"></span>
238
+
<button
239
+
onclick={() => setOpenDialog(false)}
240
+
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
241
+
>
242
+
<span class="iconify lucide--x"></span>
177
243
</button>
178
244
</div>
179
245
<form ref={formRef} class="flex flex-col gap-y-2">
180
-
<div class="flex w-fit flex-col gap-y-1 text-xs sm:text-sm">
246
+
<div class="flex w-fit flex-col gap-y-1 text-sm">
181
247
<Show when={props.create}>
182
248
<div class="flex items-center gap-x-2">
183
249
<label for="collection" class="min-w-20 select-none">
···
186
252
<TextInput
187
253
id="collection"
188
254
name="collection"
189
-
placeholder="Optional (default: record type)"
255
+
placeholder="Optional (default: $type)"
190
256
class="w-[15rem]"
191
257
/>
192
258
</div>
···
216
282
<option value="false">False</option>
217
283
</select>
218
284
</div>
219
-
<div class="flex items-center gap-2">
220
-
<Show when={!uploading()}>
221
-
<div class="dark:hover:bg-dark-200 dark:shadow-dark-800 dark:active:bg-dark-100 flex rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 text-xs font-semibold shadow-xs hover:bg-neutral-100 active:bg-neutral-200 dark:border-neutral-700 dark:bg-neutral-800">
222
-
<input type="file" id="blob" class="sr-only" onChange={() => uploadBlob()} />
223
-
<label class="flex items-center gap-1 px-2 py-1.5 select-none" for="blob">
224
-
<span class="iconify lucide--upload text-sm"></span>
225
-
Upload
226
-
</label>
227
-
</div>
228
-
<p class="text-xs">Metadata will be pasted after the cursor</p>
229
-
</Show>
230
-
<Show when={uploading()}>
231
-
<span class="iconify lucide--loader-circle animate-spin text-xl"></span>
232
-
<p>Uploading...</p>
233
-
</Show>
234
-
</div>
235
-
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
236
-
<div class="flex items-center gap-x-2">
237
-
<label for="mimetype" class="min-w-20 select-none">
238
-
MIME type
239
-
</label>
240
-
<TextInput id="mimetype" placeholder="Optional" class="w-[15rem]" />
241
-
</div>
242
-
<div class="flex items-center gap-1">
243
-
<input id="exif-rm" type="checkbox" checked />
244
-
<label for="exif-rm" class="select-none">
245
-
Remove EXIF data
246
-
</label>
247
-
</div>
248
-
</div>
249
285
</div>
250
286
<Editor
251
287
content={JSON.stringify(props.create ? placeholder() : props.record, null, 2)}
252
288
/>
253
289
<div class="flex flex-col gap-2">
254
290
<Show when={notice()}>
255
-
<div class="text-red-500 dark:text-red-400">{notice()}</div>
291
+
<div class="text-sm text-red-500 dark:text-red-400">{notice()}</div>
256
292
</Show>
257
-
<div class="flex items-center justify-end gap-2">
258
-
<Show when={!props.create}>
259
-
<div class="flex items-center gap-1">
260
-
<input id="recreate" name="recreate" type="checkbox" />
261
-
<label for="recreate" class="text-sm select-none">
262
-
Recreate record
263
-
</label>
264
-
</div>
265
-
</Show>
266
-
<Button
267
-
onClick={() =>
268
-
props.create ?
269
-
createRecord(new FormData(formRef))
270
-
: editRecord(new FormData(formRef))
271
-
}
293
+
<div class="flex justify-between gap-2">
294
+
<div class="dark:hover:bg-dark-200 dark:shadow-dark-800 dark:active:bg-dark-100 flex w-fit rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 text-xs shadow-xs hover:bg-neutral-100 active:bg-neutral-200 dark:border-neutral-700 dark:bg-neutral-800">
295
+
<input
296
+
type="file"
297
+
id="blob"
298
+
class="sr-only"
299
+
ref={blobInput}
300
+
onChange={(e) => {
301
+
if (e.target.files !== null) setOpenUpload(true);
302
+
}}
303
+
/>
304
+
<label class="flex items-center gap-1 px-2 py-1.5 select-none" for="blob">
305
+
<span class="iconify lucide--upload"></span>
306
+
Upload
307
+
</label>
308
+
</div>
309
+
<Modal
310
+
open={openUpload()}
311
+
onClose={() => setOpenUpload(false)}
312
+
closeOnClick={false}
272
313
>
273
-
{props.create ? "Create" : "Edit"}
274
-
</Button>
314
+
<FileUpload file={blobInput.files![0]} />
315
+
</Modal>
316
+
<div class="flex items-center justify-end gap-2">
317
+
<Show when={!props.create}>
318
+
<div class="flex items-center gap-1">
319
+
<input id="recreate" name="recreate" type="checkbox" />
320
+
<label for="recreate" class="text-sm select-none">
321
+
Recreate record
322
+
</label>
323
+
</div>
324
+
</Show>
325
+
<Button
326
+
onClick={() =>
327
+
props.create ?
328
+
createRecord(new FormData(formRef))
329
+
: editRecord(new FormData(formRef))
330
+
}
331
+
>
332
+
{props.create ? "Create" : "Edit"}
333
+
</Button>
334
+
</div>
275
335
</div>
276
336
</div>
277
337
</form>
+33
-38
src/components/json.tsx
+33
-38
src/components/json.tsx
···
47
47
["http:", "https:", "web+at:"].includes(new URL(part).protocol) &&
48
48
part.split("\n").length === 1
49
49
) ?
50
-
<a
51
-
class="text-blue-400 hover:underline active:underline"
52
-
href={part}
53
-
target="_blank"
54
-
rel="noopener noreferrer"
55
-
>
50
+
<a class="underline" href={part} target="_blank" rel="noopener noreferrer">
56
51
{part}
57
52
</a>
58
53
: part}
···
135
130
if (blob.$type === "blob") {
136
131
return (
137
132
<>
138
-
<span class="flex gap-x-1">
139
-
<Show when={blob.mimeType.startsWith("image/") && !hide()}>
140
-
<img
141
-
class="max-h-[16rem] w-fit max-w-[16rem]"
142
-
src={`https://${pds()}/xrpc/com.atproto.sync.getBlob?did=${repo}&cid=${blob.ref.$link}`}
143
-
/>
144
-
</Show>
145
-
<Show when={blob.mimeType === "video/mp4" && !hide()}>
146
-
<ErrorBoundary fallback={() => <span>Failed to load video</span>}>
147
-
<VideoPlayer did={repo} cid={blob.ref.$link} />
148
-
</ErrorBoundary>
149
-
</Show>
150
-
<span
151
-
classList={{
152
-
"flex items-center justify-between gap-1": true,
153
-
"flex-col": !hide(),
154
-
}}
155
-
>
156
-
<Show when={blob.mimeType.startsWith("image/") || blob.mimeType === "video/mp4"}>
157
-
<Tooltip text={hide() ? "Show" : "Hide"}>
158
-
<button
159
-
onclick={() => setHide(!hide())}
160
-
class={`${!hide() ? "-mt-1 -ml-0.5" : ""} flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600`}
161
-
>
162
-
<span
163
-
class={`iconify text-base ${hide() ? "lucide--eye-off" : "lucide--eye"}`}
164
-
></span>
165
-
</button>
166
-
</Tooltip>
133
+
<Show when={pds() && params.rkey}>
134
+
<span class="flex gap-x-1">
135
+
<Show when={blob.mimeType.startsWith("image/") && !hide()}>
136
+
<img
137
+
class="max-h-[16rem] w-fit max-w-[16rem]"
138
+
src={`https://${pds()}/xrpc/com.atproto.sync.getBlob?did=${repo}&cid=${blob.ref.$link}`}
139
+
/>
167
140
</Show>
168
-
<Show when={pds()}>
141
+
<Show when={blob.mimeType === "video/mp4" && !hide()}>
142
+
<ErrorBoundary fallback={() => <span>Failed to load video</span>}>
143
+
<VideoPlayer did={repo} cid={blob.ref.$link} />
144
+
</ErrorBoundary>
145
+
</Show>
146
+
<span
147
+
classList={{
148
+
"flex items-center justify-between gap-1": true,
149
+
"flex-col": !hide(),
150
+
}}
151
+
>
152
+
<Show when={blob.mimeType.startsWith("image/") || blob.mimeType === "video/mp4"}>
153
+
<Tooltip text={hide() ? "Show" : "Hide"}>
154
+
<button
155
+
onclick={() => setHide(!hide())}
156
+
class={`${!hide() ? "-mt-1 -ml-0.5" : ""} flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600`}
157
+
>
158
+
<span
159
+
class={`iconify text-base ${hide() ? "lucide--eye-off" : "lucide--eye"}`}
160
+
></span>
161
+
</button>
162
+
</Tooltip>
163
+
</Show>
169
164
<Tooltip text="Blob on PDS">
170
165
<a
171
166
href={`https://${pds()}/xrpc/com.atproto.sync.getBlob?did=${repo}&cid=${blob.ref.$link}`}
···
175
170
<span class="iconify lucide--external-link text-base"></span>
176
171
</a>
177
172
</Tooltip>
178
-
</Show>
173
+
</span>
179
174
</span>
180
-
</span>
175
+
</Show>
181
176
{rawObj}
182
177
</>
183
178
);
+76
-18
src/components/search.tsx
+76
-18
src/components/search.tsx
···
2
2
import { A, useLocation, useNavigate } from "@solidjs/router";
3
3
import { createResource, createSignal, For, onCleanup, onMount, Show } from "solid-js";
4
4
import { isTouchDevice } from "../layout";
5
+
import { appHandleLink, appList, appName, AppUrl } from "../utils/app-urls";
5
6
import { createDebouncedValue } from "../utils/hooks/debounced";
7
+
import { Modal } from "./modal";
6
8
7
9
export const [showSearch, setShowSearch] = createSignal(false);
8
10
···
66
68
input = input.trim().replace(/^@/, "");
67
69
if (!input.length) return;
68
70
setShowSearch(false);
69
-
if (input === "me" && localStorage.getItem("lastSignedIn") !== null) {
70
-
navigate(`/at://${localStorage.getItem("lastSignedIn")}`);
71
-
} else if (
72
-
!input.startsWith("https://bsky.app/") &&
73
-
(input.startsWith("https://") || input.startsWith("http://"))
74
-
) {
75
-
navigate(`/${input.replace("https://", "").replace("http://", "").replace("/", "")}`);
76
-
} else if (search()?.length) {
71
+
if (search()?.length) {
77
72
navigate(`/at://${search()![0].did}`);
73
+
} else if (input.startsWith("https://") || input.startsWith("http://")) {
74
+
const hostLength = input.indexOf("/", 8);
75
+
const host = input.slice(0, hostLength).replace("https://", "").replace("http://", "");
76
+
77
+
if (!(host in appList)) {
78
+
navigate(`/${input.replace("https://", "").replace("http://", "").replace("/", "")}`);
79
+
} else {
80
+
const app = appList[host as AppUrl];
81
+
const path = input.slice(hostLength + 1).split("/");
82
+
83
+
const uri = appHandleLink[app](path);
84
+
navigate(`/${uri}`);
85
+
}
78
86
} else {
79
-
const uri = input
80
-
.replace("at://", "")
81
-
.replace("https://bsky.app/profile/", "")
82
-
.replace("/post/", "/app.bsky.feed.post/");
83
-
const uriParts = uri.split("/");
84
-
navigate(
85
-
`/at://${uriParts[0]}${uriParts.length > 1 ? `/${uriParts.slice(1).join("/")}` : ""}`,
86
-
);
87
+
navigate(`/at://${input.replace("at://", "")}`);
87
88
}
88
-
setShowSearch(false);
89
89
};
90
90
91
91
return (
···
114
114
value={input() ?? ""}
115
115
onInput={(e) => setInput(e.currentTarget.value)}
116
116
/>
117
-
<Show when={input()}>
117
+
<Show when={input()} fallback={ListUrlsTooltip()}>
118
118
<button
119
119
type="button"
120
120
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-600 dark:active:bg-neutral-500"
···
144
144
</div>
145
145
</Show>
146
146
</form>
147
+
);
148
+
};
149
+
150
+
const ListUrlsTooltip = () => {
151
+
const [openList, setOpenList] = createSignal(false);
152
+
153
+
let urls: Record<string, AppUrl[]> = {};
154
+
for (const [appUrl, appView] of Object.entries(appList)) {
155
+
if (!urls[appView]) urls[appView] = [appUrl as AppUrl];
156
+
else urls[appView].push(appUrl as AppUrl);
157
+
}
158
+
159
+
return (
160
+
<>
161
+
<Modal open={openList()} onClose={() => setOpenList(false)}>
162
+
<div class="dark:bg-dark-300 dark:shadow-dark-800 absolute top-16 left-[50%] w-[22rem] -translate-x-1/2 rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 p-4 shadow-md transition-opacity duration-200 sm:w-[26rem] dark:border-neutral-700 starting:opacity-0">
163
+
<div class="mb-2 flex items-center gap-1 font-semibold">
164
+
<span class="iconify lucide--link"></span>
165
+
<span>Supported URLs</span>
166
+
</div>
167
+
<div class="mb-2 text-sm text-neutral-600 dark:text-neutral-400">
168
+
Links that will be parsed automatically, as long as all the data necessary is on the
169
+
URL.
170
+
</div>
171
+
<div class="flex flex-col gap-2 text-sm">
172
+
<For each={Object.entries(appName)}>
173
+
{([appView, name]) => {
174
+
return (
175
+
<div>
176
+
<p class="font-semibold">{name}</p>
177
+
<div class="grid grid-cols-2 gap-x-4 text-neutral-600 dark:text-neutral-400">
178
+
<For each={urls[appView]}>
179
+
{(url) => (
180
+
<a
181
+
href={`${url.startsWith("localhost:") ? "http://" : "https://"}${url}`}
182
+
target="_blank"
183
+
class="hover:underline active:underline"
184
+
>
185
+
{url}
186
+
</a>
187
+
)}
188
+
</For>
189
+
</div>
190
+
</div>
191
+
);
192
+
}}
193
+
</For>
194
+
</div>
195
+
</div>
196
+
</Modal>
197
+
<button
198
+
type="button"
199
+
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-600 dark:active:bg-neutral-500"
200
+
onClick={() => setOpenList(true)}
201
+
>
202
+
<span class="iconify lucide--help-circle"></span>
203
+
</button>
204
+
</>
147
205
);
148
206
};
149
207
+1
-1
src/components/video-player.tsx
+1
-1
src/components/video-player.tsx
+6
-4
src/layout.tsx
+6
-4
src/layout.tsx
···
24
24
"did:plc:oisofpd7lj26yvgiivf3lxsi": "puppy.jpg",
25
25
"did:plc:vwzwgnygau7ed7b7wt5ux7y2": "water.webp",
26
26
"did:plc:uu5axsmbm2or2dngy4gwchec": "city.webp",
27
-
"did:plc:hx53snho72xoj7zqt5uice4u": "bridge.jpg",
27
+
"did:plc:aokggmp5jzj4nc5jifhiplqc": "bridge.jpg",
28
+
"did:plc:bnqkww7bjxaacajzvu5gswdf": "forest.jpg",
29
+
"did:plc:p2cp5gopk7mgjegy6wadk3ep": "aurora.jpg",
28
30
};
29
31
30
32
const Layout = (props: RouteSectionProps<unknown>) => {
···
64
66
</Show>
65
67
</MetaProvider>
66
68
<header
67
-
class={`dark:shadow-dark-800 dark:bg-dark-300 mb-4 flex w-full items-center justify-between rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 bg-cover bg-center bg-no-repeat p-2 shadow-xs [--header-bg:#fafafa] dark:border-neutral-700 dark:[--header-bg:#2d2d2d] ${localStorage.getItem("hrt") === "true" ? "bg-[linear-gradient(to_left,transparent_0%,var(--header-bg)_80%),linear-gradient(to_bottom,#5BCEFA90_0%,#5BCEFA90_20%,#F5A9B890_20%,#F5A9B890_40%,#FFFFFF90_40%,#FFFFFF90_60%,#F5A9B890_60%,#F5A9B890_80%,#5BCEFA90_80%,#5BCEFA90_100%)]" : ""}`}
69
+
class={`dark:shadow-dark-800 dark:bg-dark-300 mb-4 flex w-full items-center justify-between rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 bg-size-[95%] bg-right bg-no-repeat p-2 shadow-xs [--header-bg:#fafafa] dark:border-neutral-700 dark:[--header-bg:#2d2d2d] ${localStorage.getItem("hrt") === "true" ? "bg-[linear-gradient(to_left,transparent_10%,var(--header-bg)_85%),linear-gradient(to_bottom,#5BCEFA90_0%,#5BCEFA90_20%,#F5A9B890_20%,#F5A9B890_40%,#FFFFFF90_40%,#FFFFFF90_60%,#F5A9B890_60%,#F5A9B890_80%,#5BCEFA90_80%,#5BCEFA90_100%)]" : ""}`}
68
70
style={{
69
71
"background-image":
70
72
props.params.repo in headers ?
71
-
`linear-gradient(to left, transparent 0%, var(--header-bg) 80%), url(/headers/${headers[props.params.repo]})`
73
+
`linear-gradient(to left, transparent 10%, var(--header-bg) 85%), url(/headers/${headers[props.params.repo]})`
72
74
: undefined,
73
75
}}
74
76
>
···
80
82
<span class="iconify tabler--binary-tree-filled text-[#76c4e5]"></span>
81
83
<span>PDSls</span>
82
84
</A>
83
-
<div class="dark:bg-dark-300/50 relative -mr-1 flex items-center gap-1 rounded-lg bg-neutral-50/50">
85
+
<div class="dark:bg-dark-300/60 relative -mr-1 flex items-center gap-1 rounded-lg bg-neutral-50/60">
84
86
<Show when={location.pathname !== "/"}>
85
87
<SearchButton />
86
88
</Show>
+11
-1
src/utils/api.ts
+11
-1
src/utils/api.ts
···
13
13
PlcDidDocumentResolver,
14
14
WellKnownHandleResolver,
15
15
} from "@atcute/identity-resolver";
16
+
import { DohJsonLexiconAuthorityResolver } from "@atcute/lexicon-resolver";
16
17
import { Did, Handle } from "@atcute/lexicons";
17
-
import { isHandle } from "@atcute/lexicons/syntax";
18
+
import { isHandle, Nsid } from "@atcute/lexicons/syntax";
18
19
import { createStore } from "solid-js/store";
19
20
import { setPDS } from "../components/navbar";
20
21
···
35
36
},
36
37
});
37
38
39
+
const authorityResolver = new DohJsonLexiconAuthorityResolver({
40
+
dohUrl: "https://mozilla.cloudflare-dns.com/dns-query",
41
+
});
42
+
38
43
const didPDSCache: Record<string, string> = {};
39
44
const [labelerCache, setLabelerCache] = createStore<Record<string, string>>({});
40
45
const didDocCache: Record<string, DidDocument> = {};
···
99
104
return pds;
100
105
};
101
106
107
+
const resolveLexiconAuthority = async (nsid: Nsid) => {
108
+
return await authorityResolver.resolve(nsid);
109
+
};
110
+
102
111
interface LinkData {
103
112
links: {
104
113
[key: string]: {
···
162
171
labelerCache,
163
172
resolveDidDoc,
164
173
resolveHandle,
174
+
resolveLexiconAuthority,
165
175
resolvePDS,
166
176
validateHandle,
167
177
type LinkData,
+119
src/utils/app-urls.ts
+119
src/utils/app-urls.ts
···
1
+
export type AppUrl = `${string}.${string}` | `localhost:${number}`;
2
+
3
+
export enum App {
4
+
Bluesky,
5
+
Tangled,
6
+
Whitewind,
7
+
Frontpage,
8
+
Pinksea,
9
+
Linkat,
10
+
}
11
+
12
+
export const appName = {
13
+
[App.Bluesky]: "Bluesky",
14
+
[App.Tangled]: "Tangled",
15
+
[App.Whitewind]: "Whitewind",
16
+
[App.Frontpage]: "Frontpage",
17
+
[App.Pinksea]: "Pinksea",
18
+
[App.Linkat]: "Linkat",
19
+
};
20
+
21
+
export const appList: Record<AppUrl, App> = {
22
+
"localhost:19006": App.Bluesky,
23
+
"blacksky.community": App.Bluesky,
24
+
"bsky.app": App.Bluesky,
25
+
"catsky.social": App.Bluesky,
26
+
"deer.aylac.top": App.Bluesky,
27
+
"deer-social-ayla.pages.dev": App.Bluesky,
28
+
"deer.social": App.Bluesky,
29
+
"main.bsky.dev": App.Bluesky,
30
+
"social.daniela.lol": App.Bluesky,
31
+
"tangled.org": App.Tangled,
32
+
"whtwnd.com": App.Whitewind,
33
+
"frontpage.fyi": App.Frontpage,
34
+
"pinksea.art": App.Pinksea,
35
+
"linkat.blue": App.Linkat,
36
+
};
37
+
38
+
export const appHandleLink: Record<App, (url: string[]) => string> = {
39
+
[App.Bluesky]: (path) => {
40
+
const baseType = path[0];
41
+
const user = path[1];
42
+
43
+
if (baseType === "profile") {
44
+
if (path[2]) {
45
+
const type = path[2];
46
+
const rkey = path[3];
47
+
48
+
if (type === "post") {
49
+
return `at://${user}/app.bsky.feed.post/${rkey}`;
50
+
} else if (type === "list") {
51
+
return `at://${user}/app.bsky.graph.list/${rkey}`;
52
+
} else if (type === "feed") {
53
+
return `at://${user}/app.bsky.feed.generator/${rkey}`;
54
+
} else if (type === "follows") {
55
+
return `at://${user}/app.bsky.graph.follow/${rkey}`;
56
+
}
57
+
} else {
58
+
return `at://${user}`;
59
+
}
60
+
} else if (baseType === "starter-pack") {
61
+
return `at://${user}/app.bsky.graph.starterpack/${path[2]}`;
62
+
}
63
+
return `at://${user}`;
64
+
},
65
+
[App.Tangled]: (path) => {
66
+
if (path[0] === "strings") {
67
+
return `at://${path[1]}/sh.tangled.string/${path[2]}`;
68
+
}
69
+
70
+
let query: string | undefined;
71
+
if (path[path.length - 1].includes("?")) {
72
+
const split = path[path.length - 1].split("?");
73
+
query = split[1];
74
+
path[path.length - 1] = split[0];
75
+
}
76
+
77
+
const user = path[0].replace("@", "");
78
+
79
+
if (path.length === 1) {
80
+
if (query === "tab=repos") {
81
+
return `at://${user}/sh.tangled.repo`;
82
+
} else if (query === "tab=starred") {
83
+
return `at://${user}/sh.tangled.feed.star`;
84
+
} else if (query === "tab=strings") {
85
+
return `at://${user}/sh.tangled.string`;
86
+
}
87
+
} else if (path.length === 2) {
88
+
// no way to convert the repo name to an rkey afaik
89
+
// same reason why there's nothing related to issues in here
90
+
return `at://${user}/sh.tangled.repo`;
91
+
}
92
+
93
+
return `at://${user}`;
94
+
},
95
+
[App.Whitewind]: (path) => {
96
+
if (path.length === 2) {
97
+
return `at://${path[0]}/com.whtwnd.blog.entry/${path[1]}`;
98
+
}
99
+
100
+
return `at://${path[0]}/com.whtwnd.blog.entry`;
101
+
},
102
+
[App.Frontpage]: (path) => {
103
+
if (path.length === 3) {
104
+
return `at://${path[1]}/fyi.unravel.frontpage.post/${path[2]}`;
105
+
} else if (path.length === 5) {
106
+
return `at://${path[3]}/fyi.unravel.frontpage.comment/${path[4]}`;
107
+
}
108
+
109
+
return `at://${path[0]}`;
110
+
},
111
+
[App.Pinksea]: (path) => {
112
+
if (path.length === 2) {
113
+
return `at://${path[0]}/com.shinolabs.pinksea.oekaki/${path[1]}`;
114
+
}
115
+
116
+
return `at://${path[0]}`;
117
+
},
118
+
[App.Linkat]: (path) => `at://${path[0]}/blue.linkat.board/self`,
119
+
};
+17
-9
src/views/collection.tsx
+17
-9
src/views/collection.tsx
···
18
18
19
19
interface AtprotoRecord {
20
20
rkey: string;
21
+
cid: string;
21
22
record: InferXRPCBodyOutput<ComAtprotoRepoGetRecord.mainSchema["output"]>;
22
23
timestamp: number | undefined;
23
24
toDelete: boolean;
···
40
41
41
42
return (
42
43
<span
43
-
class="relative flex items-baseline rounded px-0.5 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
44
+
class="relative flex w-full min-w-0 items-baseline rounded px-0.5 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
44
45
ref={rkeyRef}
45
46
onmouseover={() => setHover(true)}
46
47
onmouseleave={() => setHover(false)}
47
48
>
48
-
<span class="text-sm text-blue-400 sm:text-base">{props.record.rkey}</span>
49
-
<Show when={props.record.timestamp && props.record.timestamp <= Date.now()}>
50
-
<span class="ml-1 text-xs text-neutral-500 dark:text-neutral-400">
51
-
{localDateFromTimestamp(props.record.timestamp!)}
49
+
<span class="flex items-baseline truncate">
50
+
<span class="shrink-0 text-sm text-blue-400 sm:text-base">{props.record.rkey}</span>
51
+
<span class="ml-1 truncate text-xs text-neutral-500 dark:text-neutral-400" dir="rtl">
52
+
{props.record.cid}
52
53
</span>
53
-
</Show>
54
+
<Show when={props.record.timestamp && props.record.timestamp <= Date.now()}>
55
+
<span class="ml-1 shrink-0 text-xs">
56
+
{localDateFromTimestamp(props.record.timestamp!)}
57
+
</span>
58
+
</Show>
59
+
</span>
54
60
<Show when={hover()}>
55
61
<span
56
62
ref={previewRef}
···
99
105
const rkey = record.uri.split("/").pop()!;
100
106
tmpRecords.push({
101
107
rkey: rkey,
108
+
cid: record.cid,
102
109
record: record,
103
110
timestamp: TID.validate(rkey) ? TID.parse(rkey).timestamp / 1000 : undefined,
104
111
toDelete: false,
···
260
267
<Button onClick={() => setOpenDelete(false)}>Cancel</Button>
261
268
<Button
262
269
onClick={deleteRecords}
263
-
class={`dark:shadow-dark-800 rounded-lg px-2 py-1.5 text-xs font-semibold text-neutral-200 shadow-xs select-none ${recreate() ? "bg-green-500 hover:bg-green-400 dark:bg-green-600 dark:hover:bg-green-500" : "bg-red-500 hover:bg-red-400 active:bg-red-400"}`}
270
+
class={`dark:shadow-dark-800 rounded-lg px-2 py-1.5 text-xs text-white shadow-xs select-none ${recreate() ? "bg-green-500 hover:bg-green-400 dark:bg-green-600 dark:hover:bg-green-500" : "bg-red-500 hover:bg-red-400 active:bg-red-400"}`}
264
271
>
265
272
{recreate() ? "Recreate" : "Delete"}
266
273
</Button>
···
277
284
</A>
278
285
</Tooltip>
279
286
<TextInput
287
+
name="Filter"
280
288
placeholder="Filter by substring"
281
289
onInput={(e) => setFilter(e.currentTarget.value)}
282
290
class="grow"
···
293
301
}}
294
302
>
295
303
<span
296
-
class={`iconify ${reverse() ? "lucide--rotate-ccw" : "lucide--rotate-cw"} text-sm`}
304
+
class={`iconify ${reverse() ? "lucide--rotate-ccw" : "lucide--rotate-cw"}`}
297
305
></span>
298
306
Reverse
299
307
</Button>
···
318
326
</Show>
319
327
</div>
320
328
</StickyOverlay>
321
-
<div class="flex max-w-full flex-col font-mono">
329
+
<div class="flex max-w-full flex-col px-2 font-mono">
322
330
<For
323
331
each={records.filter((rec) =>
324
332
filter() ? JSON.stringify(rec.record.value).includes(filter()!) : true,
+2
-10
src/views/home.tsx
+2
-10
src/views/home.tsx
···
9
9
<div class="iconify lucide--search" />
10
10
<span>
11
11
Browse the public data on{" "}
12
-
<a
13
-
class="text-blue-400 hover:underline active:underline"
14
-
href="https://atproto.com"
15
-
target="_blank"
16
-
>
12
+
<a class="underline" href="https://atproto.com" target="_blank">
17
13
atproto
18
14
</a>
19
15
.
···
31
27
<div class="iconify lucide--send-to-back" />
32
28
<span>
33
29
Backlinks support with{" "}
34
-
<a
35
-
href="https://constellation.microcosm.blue"
36
-
class="text-blue-400 hover:underline active:underline"
37
-
target="_blank"
38
-
>
30
+
<a href="https://constellation.microcosm.blue" class="underline" target="_blank">
39
31
constellation
40
32
</a>
41
33
.
+4
-6
src/views/labels.tsx
+4
-6
src/views/labels.tsx
···
68
68
initQuery();
69
69
}}
70
70
>
71
-
<div class="w-full">
72
-
<label for="patterns" class="ml-0.5 text-sm">
73
-
URI Patterns (comma-separated)
74
-
</label>
75
-
</div>
76
-
<div class="flex w-full items-center gap-x-1">
71
+
<label for="patterns" class="ml-2 w-full text-sm">
72
+
URI Patterns (comma-separated)
73
+
</label>
74
+
<div class="flex w-full items-center gap-x-1 px-1">
77
75
<textarea
78
76
id="patterns"
79
77
name="patterns"
+1
src/views/logs.tsx
+1
src/views/logs.tsx
···
37
37
classList={{
38
38
"flex items-center rounded-full p-1.5": true,
39
39
"bg-neutral-700 dark:bg-neutral-200": activePlcEvent() === props.event,
40
+
"hover:bg-neutral-200 dark:hover:bg-neutral-700": activePlcEvent() !== props.event,
40
41
}}
41
42
onclick={() => setActivePlcEvent(activePlcEvent() === props.event ? undefined : props.event)}
42
43
>
+134
-44
src/views/pds.tsx
+134
-44
src/views/pds.tsx
···
2
2
import { Client, CredentialManager } from "@atcute/client";
3
3
import { InferXRPCBodyOutput } from "@atcute/lexicons";
4
4
import * as TID from "@atcute/tid";
5
-
import { A, useParams } from "@solidjs/router";
5
+
import { A, useLocation, useParams } from "@solidjs/router";
6
6
import { createResource, createSignal, For, Show } from "solid-js";
7
7
import { Button } from "../components/button";
8
8
import { Modal } from "../components/modal";
9
9
import { setPDS } from "../components/navbar";
10
10
import Tooltip from "../components/tooltip";
11
+
import { addToClipboard } from "../utils/copy";
11
12
import { localDateFromTimestamp } from "../utils/date";
12
13
13
14
const LIMIT = 1000;
14
15
15
16
const PdsView = () => {
16
17
const params = useParams();
18
+
const location = useLocation();
17
19
const [version, setVersion] = createSignal<string>();
18
20
const [serverInfos, setServerInfos] =
19
21
createSignal<InferXRPCBodyOutput<ComAtprotoServerDescribeServer.mainSchema["output"]>>();
···
28
30
setVersion((res.data as any).version);
29
31
};
30
32
33
+
const describeServer = async () => {
34
+
const res = await rpc.get("com.atproto.server.describeServer");
35
+
if (!res.ok) console.error(res.data.error);
36
+
else setServerInfos(res.data);
37
+
};
38
+
31
39
const fetchRepos = async () => {
32
40
getVersion();
33
-
const describeRes = await rpc.get("com.atproto.server.describeServer");
34
-
if (!describeRes.ok) console.error(describeRes.data.error);
35
-
else setServerInfos(describeRes.data);
41
+
describeServer();
36
42
const res = await rpc.get("com.atproto.sync.listRepos", {
37
43
params: { limit: LIMIT, cursor: cursor() },
38
44
});
···
52
58
<div class="flex items-center">
53
59
<A
54
60
href={`/at://${repo.did}`}
55
-
class="grow truncate rounded py-0.5 font-mono text-blue-400 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
61
+
class="grow truncate rounded py-0.5 font-mono hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
56
62
>
57
63
{repo.did}
58
64
</A>
59
65
<Show when={!repo.active}>
60
66
<Tooltip text={repo.status ?? "Unknown status"}>
61
-
<span class="iconify lucide--unplug"></span>
67
+
<span class="iconify lucide--unplug text-red-500 dark:text-red-400"></span>
62
68
</Tooltip>
63
69
</Show>
64
70
<button
···
103
109
);
104
110
};
105
111
112
+
const Tab = (props: { tab: "repos" | "info"; label: string }) => (
113
+
<div class="flex items-center gap-0.5">
114
+
<A
115
+
classList={{
116
+
"flex items-center gap-1 border-b-2": true,
117
+
"border-transparent hover:border-neutral-400 dark:hover:border-neutral-600":
118
+
(!!location.hash && location.hash !== `#${props.tab}`) ||
119
+
(!location.hash && props.tab !== "repos"),
120
+
}}
121
+
href={`/${params.pds}#${props.tab}`}
122
+
>
123
+
{props.label}
124
+
</A>
125
+
</div>
126
+
);
127
+
106
128
return (
107
129
<Show when={repos() || response()}>
108
-
<div class="flex w-full flex-col px-2">
109
-
<Show when={version()}>
110
-
{(version) => (
111
-
<div class="flex items-baseline gap-x-1">
112
-
<span class="font-semibold">Version</span>
113
-
<span class="truncate text-sm">{version()}</span>
130
+
<div class="flex w-full flex-col">
131
+
<div class="dark:shadow-dark-800 dark:bg-dark-300 mb-2 flex w-full justify-between rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm shadow-xs dark:border-neutral-700">
132
+
<div class="flex gap-3">
133
+
<Tab tab="repos" label="Repositories" />
134
+
<Tab tab="info" label="Info" />
135
+
</div>
136
+
<div class="flex gap-1">
137
+
<Tooltip text="Copy PDS">
138
+
<button
139
+
onClick={() => addToClipboard(params.pds)}
140
+
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
141
+
>
142
+
<span class="iconify lucide--copy"></span>
143
+
</button>
144
+
</Tooltip>
145
+
<Tooltip text="Firehose">
146
+
<A
147
+
href={`/firehose?instance=wss://${params.pds}`}
148
+
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
149
+
>
150
+
<span class="iconify lucide--radio-tower"></span>
151
+
</A>
152
+
</Tooltip>
153
+
</div>
154
+
</div>
155
+
<div class="flex flex-col gap-1 px-2">
156
+
<Show when={!location.hash || location.hash === "#repos"}>
157
+
<div class="flex flex-col divide-y-[0.5px] divide-neutral-300 dark:divide-neutral-700">
158
+
<For each={repos()}>{(repo) => <RepoCard {...repo} />}</For>
114
159
</div>
115
-
)}
116
-
</Show>
117
-
<Show when={serverInfos()}>
118
-
{(server) => (
119
-
<>
120
-
<Show when={server().inviteCodeRequired}>
121
-
<span class="font-semibold">Invite Code Required</span>
122
-
</Show>
123
-
<Show when={server().phoneVerificationRequired}>
124
-
<span class="font-semibold">Phone Verification Required</span>
125
-
</Show>
126
-
<Show when={server().availableUserDomains.length}>
127
-
<div class="flex flex-col">
128
-
<span class="font-semibold">Available User Domains</span>
129
-
<For each={server().availableUserDomains}>
130
-
{(domain) => <span class="text-sm wrap-anywhere">{domain}</span>}
131
-
</For>
160
+
</Show>
161
+
<Show when={location.hash === "#info"}>
162
+
<Show when={version()}>
163
+
{(version) => (
164
+
<div class="flex items-baseline gap-x-1">
165
+
<span class="font-semibold">Version</span>
166
+
<span class="truncate text-sm">{version()}</span>
132
167
</div>
133
-
</Show>
134
-
</>
135
-
)}
136
-
</Show>
137
-
<p class="w-full font-semibold">{repos()?.length} Repositories</p>
138
-
<div class="flex flex-col divide-y-[0.5px] divide-neutral-300 dark:divide-neutral-700">
139
-
<For each={repos()}>{(repo) => <RepoCard {...repo} />}</For>
168
+
)}
169
+
</Show>
170
+
<Show when={serverInfos()}>
171
+
{(server) => (
172
+
<>
173
+
<div class="flex items-baseline gap-x-1">
174
+
<span class="font-semibold">DID</span>
175
+
<span class="truncate text-sm">{server().did}</span>
176
+
</div>
177
+
<Show when={server().inviteCodeRequired}>
178
+
<span class="font-semibold">Invite Code Required</span>
179
+
</Show>
180
+
<Show when={server().phoneVerificationRequired}>
181
+
<span class="font-semibold">Phone Verification Required</span>
182
+
</Show>
183
+
<Show when={server().availableUserDomains.length}>
184
+
<div class="flex flex-col">
185
+
<span class="font-semibold">Available User Domains</span>
186
+
<For each={server().availableUserDomains}>
187
+
{(domain) => <span class="text-sm wrap-anywhere">{domain}</span>}
188
+
</For>
189
+
</div>
190
+
</Show>
191
+
<Show when={server().links?.privacyPolicy}>
192
+
<div class="flex flex-col">
193
+
<span class="font-semibold">Privacy Policy</span>
194
+
<a
195
+
href={server().links?.privacyPolicy}
196
+
class="text-sm hover:underline"
197
+
target="_blank"
198
+
>
199
+
{server().links?.privacyPolicy}
200
+
</a>
201
+
</div>
202
+
</Show>
203
+
<Show when={server().links?.termsOfService}>
204
+
<div class="flex flex-col">
205
+
<span class="font-semibold">Terms of Service</span>
206
+
<a
207
+
href={server().links?.termsOfService}
208
+
class="text-sm hover:underline"
209
+
target="_blank"
210
+
>
211
+
{server().links?.termsOfService}
212
+
</a>
213
+
</div>
214
+
</Show>
215
+
<Show when={server().contact?.email}>
216
+
<div class="flex flex-col">
217
+
<span class="font-semibold">Contact</span>
218
+
<a href={`mailto:${server().contact?.email}`} class="text-sm hover:underline">
219
+
{server().contact?.email}
220
+
</a>
221
+
</div>
222
+
</Show>
223
+
</>
224
+
)}
225
+
</Show>
226
+
</Show>
140
227
</div>
141
228
</div>
142
-
<Show when={cursor()}>
143
-
<div class="dark:bg-dark-500 fixed bottom-0 z-5 flex w-screen justify-center bg-neutral-100 py-3">
144
-
<Show when={!response.loading}>
145
-
<Button onClick={() => refetch()}>Load More</Button>
146
-
</Show>
147
-
<Show when={response.loading}>
148
-
<span class="iconify lucide--loader-circle animate-spin py-3.5 text-xl"></span>
149
-
</Show>
229
+
<Show when={!location.hash || location.hash === "#repos"}>
230
+
<div class="dark:bg-dark-500 fixed bottom-0 z-5 flex w-screen justify-center bg-neutral-100 py-2">
231
+
<div class="flex flex-col items-center gap-1 pb-2">
232
+
<p>{repos()?.length} loaded</p>
233
+
<Show when={!response.loading && cursor()}>
234
+
<Button onClick={() => refetch()}>Load More</Button>
235
+
</Show>
236
+
<Show when={response.loading}>
237
+
<span class="iconify lucide--loader-circle animate-spin py-3.5 text-xl"></span>
238
+
</Show>
239
+
</div>
150
240
</div>
151
241
</Show>
152
242
</Show>
+107
-57
src/views/record.tsx
+107
-57
src/views/record.tsx
···
1
1
import { Client, CredentialManager } from "@atcute/client";
2
2
import { lexiconDoc } from "@atcute/lexicon-doc";
3
-
import { ActorIdentifier, is, ResourceUri } from "@atcute/lexicons";
3
+
import { ActorIdentifier, is, Nsid, ResourceUri } from "@atcute/lexicons";
4
4
import { A, useLocation, useNavigate, useParams } from "@solidjs/router";
5
5
import { createResource, createSignal, ErrorBoundary, Show, Suspense } from "solid-js";
6
6
import { Backlinks } from "../components/backlinks.jsx";
···
10
10
import { JSONValue } from "../components/json.jsx";
11
11
import { agent } from "../components/login.jsx";
12
12
import { Modal } from "../components/modal.jsx";
13
-
import { pds, setCID } from "../components/navbar.jsx";
13
+
import { pds } from "../components/navbar.jsx";
14
14
import Tooltip from "../components/tooltip.jsx";
15
15
import { setNotif } from "../layout.jsx";
16
-
import { didDocCache, resolvePDS } from "../utils/api.js";
16
+
import { didDocCache, resolveLexiconAuthority, resolvePDS } from "../utils/api.js";
17
17
import { AtUri, uriTemplates } from "../utils/templates.js";
18
18
import { lexicons } from "../utils/types/lexicons.js";
19
19
import { verifyRecord } from "../utils/verify.js";
···
27
27
const [externalLink, setExternalLink] = createSignal<
28
28
{ label: string; link: string; icon?: string } | undefined
29
29
>();
30
+
const [lexiconUri, setLexiconUri] = createSignal<string>();
30
31
const [validRecord, setValidRecord] = createSignal<boolean | undefined>(undefined);
31
32
const [validSchema, setValidSchema] = createSignal<boolean | undefined>(undefined);
32
33
const did = params.repo;
33
34
let rpc: Client;
34
35
35
36
const fetchRecord = async () => {
36
-
setCID(undefined);
37
37
setValidRecord(undefined);
38
38
setValidSchema(undefined);
39
+
setLexiconUri(undefined);
39
40
const pds = await resolvePDS(did);
40
41
rpc = new Client({ handler: new CredentialManager({ service: pds }) });
41
42
const res = await rpc.get("com.atproto.repo.getRecord", {
···
50
51
setNotice(res.data.error);
51
52
throw new Error(res.data.error);
52
53
}
53
-
setCID(res.data.cid);
54
54
setExternalLink(checkUri(res.data.uri, res.data.value));
55
+
resolveLexicon(params.collection as Nsid);
55
56
verify(res.data);
56
57
57
58
return res.data;
···
94
95
}
95
96
};
96
97
98
+
const resolveLexicon = async (nsid: Nsid) => {
99
+
try {
100
+
const res = await resolveLexiconAuthority(nsid);
101
+
setLexiconUri(`at://${res}/com.atproto.lexicon.schema/${nsid}`);
102
+
} catch {}
103
+
};
104
+
97
105
const [record, { refetch }] = createResource(fetchRecord);
98
106
99
107
const deleteRecord = async () => {
···
118
126
if (!template) return undefined;
119
127
return template(parsedUri, record);
120
128
};
129
+
130
+
const RecordTab = (props: {
131
+
tab: "record" | "backlinks" | "info";
132
+
label: string;
133
+
error?: boolean;
134
+
}) => (
135
+
<div class="flex items-center gap-0.5">
136
+
<A
137
+
classList={{
138
+
"flex items-center gap-1 border-b-2": true,
139
+
"border-transparent hover:border-neutral-400 dark:hover:border-neutral-600":
140
+
(!!location.hash && location.hash !== `#${props.tab}`) ||
141
+
(!location.hash && props.tab !== "record"),
142
+
}}
143
+
href={`/at://${did}/${params.collection}/${params.rkey}#${props.tab}`}
144
+
>
145
+
{props.label}
146
+
</A>
147
+
<Show when={props.error && (validRecord() === false || validSchema() === false)}>
148
+
<span class="iconify lucide--x text-red-500 dark:text-red-400"></span>
149
+
</Show>
150
+
</div>
151
+
);
121
152
122
153
return (
123
154
<Show when={record()} keyed>
124
155
<div class="flex w-full flex-col items-center">
125
156
<div class="dark:shadow-dark-800 dark:bg-dark-300 mb-3 flex w-full justify-between rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm shadow-xs dark:border-neutral-700">
126
157
<div class="flex gap-3">
127
-
<A
128
-
classList={{
129
-
"flex items-center gap-1 border-b-2": true,
130
-
"border-transparent hover:border-neutral-400 dark:hover:border-neutral-600":
131
-
!!location.hash && location.hash !== "#record",
132
-
}}
133
-
href={`/at://${did}/${params.collection}/${params.rkey}#record`}
134
-
>
135
-
<div class="iconify lucide--file-json" />
136
-
Record
137
-
</A>
138
-
<A
139
-
classList={{
140
-
"flex items-center gap-1 border-b-2": true,
141
-
"border-transparent hover:border-neutral-400 dark:hover:border-neutral-600":
142
-
location.hash !== "#backlinks",
143
-
}}
144
-
href={`/at://${did}/${params.collection}/${params.rkey}#backlinks`}
145
-
>
146
-
<div class="iconify lucide--send-to-back" />
147
-
Backlinks
148
-
</A>
158
+
<RecordTab tab="record" label="Record" />
159
+
<RecordTab tab="backlinks" label="Backlinks" />
160
+
<RecordTab tab="info" label="Info" error />
149
161
</div>
150
162
<div class="flex gap-1">
151
-
<div class="mr-1 flex gap-3">
152
-
<Tooltip
153
-
text={
154
-
validRecord() === undefined ? "Validating"
155
-
: validRecord() === false ?
156
-
"Invalid record"
157
-
: "Valid record"
158
-
}
159
-
>
160
-
<span
161
-
classList={{
162
-
"iconify lucide--lock-keyhole": validRecord() === true,
163
-
"iconify lucide--lock-keyhole-open text-red-500 dark:text-red-400":
164
-
validRecord() === false,
165
-
"iconify lucide--loader-circle animate-spin": validRecord() === undefined,
166
-
}}
167
-
></span>
168
-
</Tooltip>
169
-
<Show when={validSchema() !== undefined}>
170
-
<Tooltip text={validSchema() ? "Valid schema" : "Invalid schema"}>
171
-
<span
172
-
class={`iconify ${validSchema() ? "lucide--file-check" : "lucide--file-x text-red-500 dark:text-red-400"}`}
173
-
></span>
174
-
</Tooltip>
175
-
</Show>
176
-
</div>
177
163
<Show when={agent() && agent()?.sub === record()?.uri.split("/")[2]}>
178
164
<RecordEditor create={false} record={record()?.value} refetch={refetch} />
179
165
<Tooltip text="Delete">
···
191
177
<Button onClick={() => setOpenDelete(false)}>Cancel</Button>
192
178
<Button
193
179
onClick={deleteRecord}
194
-
class="dark:shadow-dark-800 rounded-lg bg-red-500 px-2 py-1.5 text-xs font-semibold text-neutral-200 shadow-xs select-none hover:bg-red-400 active:bg-red-400"
180
+
class="dark:shadow-dark-800 rounded-lg bg-red-500 px-2 py-1.5 text-xs text-white shadow-xs select-none hover:bg-red-400 active:bg-red-400"
195
181
>
196
182
Delete
197
183
</Button>
···
210
196
label="Copy record"
211
197
icon="lucide--copy"
212
198
/>
199
+
<Show when={record()?.cid}>
200
+
{(cid) => <CopyMenu copyContent={cid()} label="Copy CID" icon="lucide--copy" />}
201
+
</Show>
213
202
<Show when={externalLink()}>
214
203
{(externalLink) => (
215
204
<NavMenu
···
231
220
</div>
232
221
</div>
233
222
<Show when={!location.hash || location.hash === "#record"}>
234
-
<Show when={validRecord() === false}>
235
-
<div class="mb-2 break-words text-red-500 dark:text-red-400">{notice()}</div>
236
-
</Show>
237
223
<div class="w-max max-w-screen min-w-full px-4 font-mono text-xs wrap-anywhere whitespace-pre-wrap sm:px-2 sm:text-sm md:max-w-[48rem]">
238
224
<JSONValue data={record()?.value as any} repo={record()!.uri.split("/")[2]} />
239
225
</div>
···
250
236
</div>
251
237
</Suspense>
252
238
</ErrorBoundary>
239
+
</Show>
240
+
<Show when={location.hash === "#info"}>
241
+
<div class="flex w-full flex-col gap-2 px-2 text-sm">
242
+
<div>
243
+
<div class="flex items-center gap-1">
244
+
<span class="iconify lucide--at-sign"></span>
245
+
<p class="font-semibold">AT URI</p>
246
+
</div>
247
+
<div class="truncate text-xs">{record()?.uri}</div>
248
+
</div>
249
+
<Show when={record()?.cid}>
250
+
<div>
251
+
<div class="flex items-center gap-1">
252
+
<span class="iconify lucide--box"></span>
253
+
<p class="font-semibold">CID</p>
254
+
</div>
255
+
<div class="truncate text-left text-xs" dir="rtl">
256
+
{record()?.cid}
257
+
</div>
258
+
</div>
259
+
</Show>
260
+
<div>
261
+
<div class="flex items-center gap-1">
262
+
<span class="iconify lucide--lock-keyhole"></span>
263
+
<p class="font-semibold">Record verification</p>
264
+
<span
265
+
classList={{
266
+
"iconify lucide--check text-green-500 dark:text-green-400":
267
+
validRecord() === true,
268
+
"iconify lucide--x text-red-500 dark:text-red-400": validRecord() === false,
269
+
"iconify lucide--loader-circle animate-spin": validRecord() === undefined,
270
+
}}
271
+
></span>
272
+
</div>
273
+
<Show when={validRecord() === false}>
274
+
<div class="break-words">{notice()}</div>
275
+
</Show>
276
+
</div>
277
+
<Show when={validSchema() !== undefined}>
278
+
<div class="flex items-center gap-1">
279
+
<span class="iconify lucide--file-check"></span>
280
+
<p class="font-semibold">Schema validation</p>
281
+
<span
282
+
class={`iconify ${validSchema() ? "lucide--check text-green-500 dark:text-green-400" : "lucide--x text-red-500 dark:text-red-400"}`}
283
+
></span>
284
+
</div>
285
+
</Show>
286
+
<Show when={lexiconUri()}>
287
+
<div>
288
+
<div class="flex items-center gap-1">
289
+
<span class="iconify lucide--scroll-text"></span>
290
+
<p class="font-semibold">Lexicon schema</p>
291
+
</div>
292
+
<div class="truncate text-xs">
293
+
<A
294
+
href={`/${lexiconUri()}`}
295
+
class="text-blue-400 hover:underline active:underline"
296
+
>
297
+
{lexiconUri()}
298
+
</A>
299
+
</div>
300
+
</div>
301
+
</Show>
302
+
</div>
253
303
</Show>
254
304
</div>
255
305
</Show>
+30
-59
src/views/repo.tsx
+30
-59
src/views/repo.tsx
···
130
130
setDownloading(false);
131
131
};
132
132
133
-
const toggleCollection = (authority: string) => {
134
-
setNsids({
135
-
...nsids(),
136
-
[authority]: { ...nsids()![authority], hidden: !nsids()![authority].hidden },
137
-
});
138
-
};
139
-
140
133
return (
141
134
<Show when={repo()}>
142
135
<div class="flex w-full flex-col gap-2 break-words">
···
223
216
<TextInput
224
217
name="filter"
225
218
placeholder="Filter collections"
226
-
onInput={(e) => setFilter(e.currentTarget.value)}
219
+
onInput={(e) => setFilter(e.currentTarget.value.toLowerCase())}
227
220
class="grow"
228
221
/>
229
-
<div class="flex flex-col font-mono">
230
-
<div class="grid grid-cols-[min-content_1fr] items-center gap-x-2 overflow-hidden text-sm">
231
-
<For
232
-
each={Object.keys(nsids() ?? {}).filter((authority) =>
233
-
filter() ?
234
-
authority.startsWith(filter()!) || filter()?.startsWith(authority)
235
-
: true,
236
-
)}
237
-
>
238
-
{(authority) => (
239
-
<>
240
-
<button onclick={() => toggleCollection(authority)} class="flex items-center">
241
-
<span
242
-
classList={{
243
-
"iconify lucide--chevron-down text-lg transition-transform": true,
244
-
"-rotate-90": nsids()?.[authority].hidden,
245
-
}}
246
-
></span>
247
-
</button>
248
-
<button
249
-
class="bg-transparent text-left wrap-anywhere"
250
-
onclick={() => toggleCollection(authority)}
251
-
>
252
-
{authority}
253
-
</button>
254
-
<Show when={!nsids()?.[authority].hidden}>
255
-
<div></div>
256
-
<div class="flex flex-col">
257
-
<For
258
-
each={nsids()?.[authority].nsids.filter((nsid) =>
259
-
filter() ?
260
-
nsid.startsWith(filter()!.split(".").slice(2).join("."))
261
-
: true,
262
-
)}
263
-
>
264
-
{(nsid) => (
265
-
<A
266
-
href={`/at://${did}/${authority}.${nsid}`}
267
-
class="text-blue-400 hover:underline active:underline"
268
-
>
269
-
{authority}.{nsid}
270
-
</A>
271
-
)}
272
-
</For>
273
-
</div>
274
-
</Show>
275
-
</>
276
-
)}
277
-
</For>
278
-
</div>
222
+
<div class="flex flex-col overflow-hidden font-mono text-sm">
223
+
<For
224
+
each={Object.keys(nsids() ?? {}).filter((authority) =>
225
+
filter() ?
226
+
authority.startsWith(filter()!) || filter()?.startsWith(authority)
227
+
: true,
228
+
)}
229
+
>
230
+
{(authority) => (
231
+
<div class="dark:hover:bg-dark-200 flex flex-col rounded-lg p-1 hover:bg-neutral-200">
232
+
<For
233
+
each={nsids()?.[authority].nsids.filter((nsid) =>
234
+
filter() ? nsid.startsWith(filter()!.split(".").slice(2).join(".")) : true,
235
+
)}
236
+
>
237
+
{(nsid) => (
238
+
<A
239
+
href={`/at://${did}/${authority}.${nsid}`}
240
+
class="hover:underline active:underline"
241
+
>
242
+
<span>{authority}</span>
243
+
<span class="text-neutral-500 dark:text-neutral-400">.{nsid}</span>
244
+
</A>
245
+
)}
246
+
</For>
247
+
</div>
248
+
)}
249
+
</For>
279
250
</div>
280
251
</Show>
281
252
<Show when={location.hash === "#identity"}>
···
350
321
<li class="flex flex-col text-sm">
351
322
<span>#{service.id.split("#")[1]}</span>
352
323
<a
353
-
class="w-fit text-blue-400 hover:underline active:underline"
324
+
class="w-fit underline"
354
325
href={service.serviceEndpoint.toString()}
355
326
target="_blank"
356
327
>