@vertesia/tools-admin-ui 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +120 -0
  3. package/lib/AdminApp.d.ts +13 -0
  4. package/lib/AdminApp.d.ts.map +1 -0
  5. package/lib/AdminContext.d.ts +10 -0
  6. package/lib/AdminContext.d.ts.map +1 -0
  7. package/lib/components/CollectionCard.d.ts +5 -0
  8. package/lib/components/CollectionCard.d.ts.map +1 -0
  9. package/lib/components/DetailPage.d.ts +13 -0
  10. package/lib/components/DetailPage.d.ts.map +1 -0
  11. package/lib/components/EndpointPanel.d.ts +5 -0
  12. package/lib/components/EndpointPanel.d.ts.map +1 -0
  13. package/lib/components/HeroSection.d.ts +9 -0
  14. package/lib/components/HeroSection.d.ts.map +1 -0
  15. package/lib/components/ResourceCard.d.ts +5 -0
  16. package/lib/components/ResourceCard.d.ts.map +1 -0
  17. package/lib/components/ResourceSection.d.ts +10 -0
  18. package/lib/components/ResourceSection.d.ts.map +1 -0
  19. package/lib/components/SearchBar.d.ts +10 -0
  20. package/lib/components/SearchBar.d.ts.map +1 -0
  21. package/lib/components/SummaryBadge.d.ts +5 -0
  22. package/lib/components/SummaryBadge.d.ts.map +1 -0
  23. package/lib/components/index.d.ts +9 -0
  24. package/lib/components/index.d.ts.map +1 -0
  25. package/lib/hooks.d.ts +26 -0
  26. package/lib/hooks.d.ts.map +1 -0
  27. package/lib/index.d.ts +7 -0
  28. package/lib/index.d.ts.map +1 -0
  29. package/lib/pages/HomePage.d.ts +2 -0
  30. package/lib/pages/HomePage.d.ts.map +1 -0
  31. package/lib/pages/InteractionCollection.d.ts +2 -0
  32. package/lib/pages/InteractionCollection.d.ts.map +1 -0
  33. package/lib/pages/InteractionDetail.d.ts +2 -0
  34. package/lib/pages/InteractionDetail.d.ts.map +1 -0
  35. package/lib/pages/SkillCollection.d.ts +2 -0
  36. package/lib/pages/SkillCollection.d.ts.map +1 -0
  37. package/lib/pages/SkillDetail.d.ts +2 -0
  38. package/lib/pages/SkillDetail.d.ts.map +1 -0
  39. package/lib/pages/TemplateCollection.d.ts +2 -0
  40. package/lib/pages/TemplateCollection.d.ts.map +1 -0
  41. package/lib/pages/TemplateDetail.d.ts +2 -0
  42. package/lib/pages/TemplateDetail.d.ts.map +1 -0
  43. package/lib/pages/ToolCollection.d.ts +2 -0
  44. package/lib/pages/ToolCollection.d.ts.map +1 -0
  45. package/lib/pages/TypeCollection.d.ts +2 -0
  46. package/lib/pages/TypeCollection.d.ts.map +1 -0
  47. package/lib/pages/TypeDetail.d.ts +2 -0
  48. package/lib/pages/TypeDetail.d.ts.map +1 -0
  49. package/lib/tools-admin-ui.js +935 -0
  50. package/lib/tools-admin-ui.js.map +1 -0
  51. package/lib/types.d.ts +89 -0
  52. package/lib/types.d.ts.map +1 -0
  53. package/package.json +50 -0
  54. package/src/AdminApp.tsx +87 -0
  55. package/src/AdminContext.ts +17 -0
  56. package/src/admin.css +650 -0
  57. package/src/components/CollectionCard.tsx +23 -0
  58. package/src/components/DetailPage.tsx +40 -0
  59. package/src/components/EndpointPanel.tsx +24 -0
  60. package/src/components/HeroSection.tsx +88 -0
  61. package/src/components/ResourceCard.tsx +25 -0
  62. package/src/components/ResourceSection.tsx +31 -0
  63. package/src/components/SearchBar.tsx +35 -0
  64. package/src/components/SummaryBadge.tsx +9 -0
  65. package/src/components/index.ts +8 -0
  66. package/src/dev/env.ts +14 -0
  67. package/src/dev/main.tsx +37 -0
  68. package/src/hooks.ts +36 -0
  69. package/src/index.ts +6 -0
  70. package/src/pages/HomePage.tsx +99 -0
  71. package/src/pages/InteractionCollection.tsx +59 -0
  72. package/src/pages/InteractionDetail.tsx +92 -0
  73. package/src/pages/SkillCollection.tsx +111 -0
  74. package/src/pages/SkillDetail.tsx +112 -0
  75. package/src/pages/TemplateCollection.tsx +54 -0
  76. package/src/pages/TemplateDetail.tsx +68 -0
  77. package/src/pages/ToolCollection.tsx +55 -0
  78. package/src/pages/TypeCollection.tsx +60 -0
  79. package/src/pages/TypeDetail.tsx +63 -0
  80. package/src/types.ts +304 -0
  81. package/src/vite-env.d.ts +1 -0
package/src/admin.css ADDED
@@ -0,0 +1,650 @@
1
+ /**
2
+ * Self-contained styles for the admin panel.
3
+ * All classes are prefixed with `vta-` (Vertesia Tools Admin) to avoid
4
+ * polluting the plugin app CSS or the host page.
5
+ */
6
+
7
+ /* ── Root container ─────────────────────────────────────────────── */
8
+
9
+ .vta-root {
10
+ max-width: 1120px;
11
+ margin: 0 auto;
12
+ padding: 2.5rem 1.75rem;
13
+ font-family: system-ui, -apple-system, sans-serif;
14
+ color: #0f172a;
15
+ line-height: 1.5;
16
+ }
17
+
18
+ /* ── Hero header ────────────────────────────────────────────────── */
19
+
20
+ .vta-hero {
21
+ display: flex;
22
+ justify-content: space-between;
23
+ align-items: flex-start;
24
+ gap: 2.25rem;
25
+ padding: 1.75rem 2rem;
26
+ margin-bottom: 2.5rem;
27
+ border-radius: 1.25rem;
28
+ background: linear-gradient(135deg, #ffffff, #f3f4ff);
29
+ border: 1px solid #e5e7eb;
30
+ box-shadow:
31
+ 0 18px 40px rgba(15, 23, 42, 0.08),
32
+ 0 0 0 1px rgba(248, 250, 252, 0.8);
33
+ }
34
+
35
+ .vta-hero-main {
36
+ flex: 1;
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: 0.75rem;
40
+ }
41
+
42
+ .vta-hero-identity {
43
+ display: flex;
44
+ align-items: center;
45
+ gap: 1rem;
46
+ }
47
+
48
+ .vta-hero-logo {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ width: 56px;
53
+ height: 56px;
54
+ border-radius: 14px;
55
+ background: radial-gradient(circle at 30% 0, #38bdf8, #6366f1);
56
+ box-shadow:
57
+ 0 0 0 1px rgba(15, 23, 42, 0.85),
58
+ 0 12px 30px rgba(37, 99, 235, 0.6);
59
+ font-size: 1.1rem;
60
+ font-weight: 650;
61
+ letter-spacing: 0.08em;
62
+ text-transform: uppercase;
63
+ color: #eff6ff;
64
+ }
65
+
66
+ .vta-hero-eyebrow {
67
+ font-size: 0.75rem;
68
+ letter-spacing: 0.12em;
69
+ text-transform: uppercase;
70
+ color: #6b7280;
71
+ margin: 0;
72
+ }
73
+
74
+ .vta-hero-title {
75
+ font-size: 1.9rem;
76
+ font-weight: 650;
77
+ letter-spacing: -0.03em;
78
+ color: #0f172a;
79
+ margin: 0;
80
+ }
81
+
82
+ .vta-hero-tagline {
83
+ font-size: 0.95rem;
84
+ color: #4b5563;
85
+ margin: 0;
86
+ }
87
+
88
+ .vta-hero-summary {
89
+ display: flex;
90
+ flex-wrap: wrap;
91
+ gap: 0.5rem;
92
+ font-size: 0.8rem;
93
+ color: #6b7280;
94
+ }
95
+
96
+ .vta-badge {
97
+ display: inline-flex;
98
+ align-items: center;
99
+ gap: 0.35rem;
100
+ padding: 0.15rem 0.55rem;
101
+ border-radius: 999px;
102
+ background: #f9fafb;
103
+ border: 1px solid #e5e7eb;
104
+ }
105
+
106
+ .vta-badge-dot {
107
+ width: 6px;
108
+ height: 6px;
109
+ border-radius: 999px;
110
+ display: inline-block;
111
+ background: #22c55e;
112
+ }
113
+
114
+ .vta-hero-links {
115
+ display: flex;
116
+ gap: 0.75rem;
117
+ flex-wrap: wrap;
118
+ margin-top: 0.25rem;
119
+ }
120
+
121
+ .vta-link-primary,
122
+ .vta-link-secondary {
123
+ display: inline-flex;
124
+ align-items: center;
125
+ gap: 0.5rem;
126
+ padding: 0.5rem 1rem;
127
+ border-radius: 6px;
128
+ font-size: 0.875rem;
129
+ font-weight: 500;
130
+ text-decoration: none;
131
+ color: white;
132
+ transition: opacity 0.15s;
133
+ }
134
+
135
+ .vta-link-primary { background: #3b82f6; }
136
+ .vta-link-secondary { background: #10b981; }
137
+ .vta-link-primary:hover { opacity: 0.88; }
138
+ .vta-link-secondary:hover { opacity: 0.88; }
139
+
140
+ /* ── Hero aside panel ───────────────────────────────────────────── */
141
+
142
+ .vta-hero-panel {
143
+ min-width: 220px;
144
+ max-width: 260px;
145
+ flex-shrink: 0;
146
+ }
147
+
148
+ .vta-endpoint {
149
+ margin-bottom: 0.75rem;
150
+ }
151
+
152
+ .vta-endpoint-label {
153
+ font-size: 0.7rem;
154
+ letter-spacing: 0.13em;
155
+ text-transform: uppercase;
156
+ color: #1d4ed8;
157
+ margin-bottom: 0.35rem;
158
+ }
159
+
160
+ .vta-endpoint-box {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 0.5rem;
164
+ background: #f3f4f6;
165
+ padding: 0.5rem 0.75rem;
166
+ border-radius: 0.5rem;
167
+ border: 1px solid #e5e7eb;
168
+ }
169
+
170
+ .vta-endpoint-code {
171
+ flex: 1;
172
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
173
+ font-size: 0.82rem;
174
+ color: #111827;
175
+ }
176
+
177
+ .vta-copy-btn {
178
+ background: #e5e7eb;
179
+ border: none;
180
+ padding: 0.35rem;
181
+ border-radius: 4px;
182
+ cursor: pointer;
183
+ color: #6b7280;
184
+ font-size: 0.8rem;
185
+ line-height: 1;
186
+ transition: all 0.15s;
187
+ }
188
+
189
+ .vta-copy-btn:hover {
190
+ background: #d1d5db;
191
+ color: #374151;
192
+ }
193
+
194
+ .vta-hero-hint {
195
+ margin-top: 0.6rem;
196
+ font-size: 0.8rem;
197
+ color: #6b7280;
198
+ line-height: 1.4;
199
+ }
200
+
201
+ .vta-hero-hint strong {
202
+ color: #111827;
203
+ }
204
+
205
+ .vta-hero-version {
206
+ font-size: 0.75rem;
207
+ color: #9ca3af;
208
+ margin-top: 0.25rem;
209
+ }
210
+
211
+ /* ── Search bar ─────────────────────────────────────────────────── */
212
+
213
+ .vta-search {
214
+ margin-bottom: 1.75rem;
215
+ }
216
+
217
+ .vta-search-input {
218
+ width: 100%;
219
+ max-width: 360px;
220
+ padding: 0.55rem 0.75rem;
221
+ border-radius: 999px;
222
+ border: 1px solid #e5e7eb;
223
+ background: #ffffff;
224
+ color: #111827;
225
+ font-size: 0.9rem;
226
+ font-family: inherit;
227
+ box-shadow: 0 4px 10px rgba(15, 23, 42, 0.04);
228
+ box-sizing: border-box;
229
+ }
230
+
231
+ .vta-search-input::placeholder { color: #9ca3af; }
232
+
233
+ .vta-search-input:focus {
234
+ outline: none;
235
+ border-color: #60a5fa;
236
+ box-shadow:
237
+ 0 0 0 1px rgba(59, 130, 246, 0.4),
238
+ 0 6px 18px rgba(37, 99, 235, 0.18);
239
+ }
240
+
241
+ .vta-search-hint {
242
+ font-size: 0.75rem;
243
+ color: #9ca3af;
244
+ margin-top: 0.4rem;
245
+ }
246
+
247
+ .vta-search-empty {
248
+ font-size: 0.85rem;
249
+ color: #ef4444;
250
+ margin-top: 0.5rem;
251
+ }
252
+
253
+ /* ── Section ────────────────────────────────────────────────────── */
254
+
255
+ .vta-divider {
256
+ border: none;
257
+ border-top: 1px solid #e5e7eb;
258
+ margin: 2rem 0;
259
+ }
260
+
261
+ .vta-section-title {
262
+ font-size: 1.4rem;
263
+ font-weight: 600;
264
+ letter-spacing: 0.03em;
265
+ color: #0f172a;
266
+ margin: 0 0 0.25rem 0;
267
+ }
268
+
269
+ .vta-section-count {
270
+ font-size: 0.85rem;
271
+ font-weight: 400;
272
+ color: #9ca3af;
273
+ margin-left: 0.5rem;
274
+ }
275
+
276
+ .vta-section-subtitle {
277
+ font-size: 0.8rem;
278
+ color: #6b7280;
279
+ margin: 0 0 1rem 0;
280
+ }
281
+
282
+ /* ── Resource card grid ─────────────────────────────────────────── */
283
+
284
+ .vta-card-grid {
285
+ display: grid;
286
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
287
+ gap: 1.5rem;
288
+ }
289
+
290
+ .vta-card {
291
+ background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),
292
+ #ffffff;
293
+ padding: 1.25rem 1.35rem;
294
+ border-radius: 14px;
295
+ box-shadow:
296
+ 0 14px 30px rgba(15, 23, 42, 0.06),
297
+ 0 0 0 1px rgba(248, 250, 252, 0.9);
298
+ border: 1px solid #e5e7eb;
299
+ transition: transform 0.15s, box-shadow 0.15s;
300
+ }
301
+
302
+ .vta-card:hover {
303
+ transform: translateY(-3px);
304
+ box-shadow:
305
+ 0 18px 40px rgba(15, 23, 42, 0.10),
306
+ 0 0 0 1px rgba(59, 130, 246, 0.6);
307
+ }
308
+
309
+ .vta-card-type {
310
+ display: inline-block;
311
+ font-size: 0.7rem;
312
+ font-weight: 600;
313
+ letter-spacing: 0.06em;
314
+ text-transform: uppercase;
315
+ padding: 0.15rem 0.55rem;
316
+ border-radius: 999px;
317
+ margin-bottom: 0.6rem;
318
+ }
319
+
320
+ /* Type-specific badge colours */
321
+ .vta-card-type--tool { background: #dbeafe; color: #1e40af; }
322
+ .vta-card-type--skill { background: #d1fae5; color: #065f46; }
323
+ .vta-card-type--interaction { background: #fef3c7; color: #92400e; }
324
+ .vta-card-type--type { background: #f3f4f6; color: #374151; }
325
+ .vta-card-type--template { background: #ede9fe; color: #5b21b6; }
326
+ .vta-card-type--mcp { background: #fce7f3; color: #9d174d; }
327
+
328
+ .vta-card-title {
329
+ font-weight: 600;
330
+ font-size: 1.05rem;
331
+ color: #0f172a;
332
+ margin-bottom: 0.25rem;
333
+ }
334
+
335
+ .vta-card-desc {
336
+ font-size: 0.875rem;
337
+ color: #6b7280;
338
+ margin-bottom: 0.5rem;
339
+ }
340
+
341
+ .vta-card-tags {
342
+ display: flex;
343
+ flex-wrap: wrap;
344
+ gap: 0.35rem;
345
+ margin-bottom: 0.4rem;
346
+ }
347
+
348
+ .vta-tag {
349
+ font-size: 0.7rem;
350
+ padding: 0.1rem 0.5rem;
351
+ border-radius: 999px;
352
+ background: #fef3c7;
353
+ color: #92400e;
354
+ }
355
+
356
+ .vta-card-url {
357
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
358
+ font-size: 0.75rem;
359
+ color: #9ca3af;
360
+ white-space: nowrap;
361
+ overflow: hidden;
362
+ text-overflow: ellipsis;
363
+ }
364
+
365
+ /* ── Card link wrapper ─────────────────────────────────────────── */
366
+
367
+ .vta-card-link {
368
+ text-decoration: none;
369
+ color: inherit;
370
+ display: block;
371
+ }
372
+
373
+ .vta-card--link {
374
+ cursor: pointer;
375
+ }
376
+
377
+ /* ── Detail page ───────────────────────────────────────────────── */
378
+
379
+ .vta-detail-nav {
380
+ display: flex;
381
+ align-items: center;
382
+ gap: 1rem;
383
+ margin-bottom: 1.25rem;
384
+ }
385
+
386
+ .vta-detail-back {
387
+ display: inline-flex;
388
+ align-items: center;
389
+ gap: 0.35rem;
390
+ font-size: 0.875rem;
391
+ color: #3b82f6;
392
+ text-decoration: none;
393
+ transition: opacity 0.15s;
394
+ }
395
+
396
+ .vta-detail-back:hover {
397
+ opacity: 0.75;
398
+ }
399
+
400
+ .vta-detail-header {
401
+ margin-bottom: 2rem;
402
+ }
403
+
404
+ .vta-detail-title {
405
+ font-size: 1.75rem;
406
+ font-weight: 650;
407
+ letter-spacing: -0.02em;
408
+ color: #0f172a;
409
+ margin: 0.5rem 0 0.25rem;
410
+ }
411
+
412
+ .vta-detail-desc {
413
+ font-size: 0.95rem;
414
+ color: #4b5563;
415
+ margin: 0 0 0.75rem;
416
+ line-height: 1.6;
417
+ }
418
+
419
+ .vta-detail-section {
420
+ margin-bottom: 2rem;
421
+ }
422
+
423
+ .vta-detail-section h2 {
424
+ font-size: 1.15rem;
425
+ font-weight: 600;
426
+ color: #0f172a;
427
+ margin: 0 0 0.75rem;
428
+ }
429
+
430
+ .vta-detail-card {
431
+ background: #ffffff;
432
+ border: 1px solid #e5e7eb;
433
+ border-radius: 10px;
434
+ padding: 1rem 1.25rem;
435
+ margin-bottom: 0.75rem;
436
+ }
437
+
438
+ .vta-detail-card-header {
439
+ display: flex;
440
+ align-items: center;
441
+ gap: 0.5rem;
442
+ margin-bottom: 0.5rem;
443
+ }
444
+
445
+ .vta-detail-role {
446
+ display: inline-block;
447
+ font-size: 0.7rem;
448
+ font-weight: 600;
449
+ letter-spacing: 0.06em;
450
+ text-transform: uppercase;
451
+ padding: 0.15rem 0.55rem;
452
+ border-radius: 999px;
453
+ }
454
+
455
+ .vta-detail-role--system { background: #dbeafe; color: #1e40af; }
456
+ .vta-detail-role--user { background: #d1fae5; color: #065f46; }
457
+ .vta-detail-role--assistant { background: #ede9fe; color: #5b21b6; }
458
+ .vta-detail-role--safety { background: #fce7f3; color: #9d174d; }
459
+ .vta-detail-role--tool { background: #fef3c7; color: #92400e; }
460
+
461
+ .vta-detail-prompt-name {
462
+ font-size: 0.8rem;
463
+ color: #6b7280;
464
+ font-style: italic;
465
+ }
466
+
467
+ .vta-detail-code {
468
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
469
+ font-size: 0.82rem;
470
+ line-height: 1.6;
471
+ background: #f9fafb;
472
+ border: 1px solid #e5e7eb;
473
+ border-radius: 8px;
474
+ padding: 0.75rem 1rem;
475
+ margin: 0;
476
+ overflow-x: auto;
477
+ white-space: pre-wrap;
478
+ word-break: break-word;
479
+ color: #111827;
480
+ }
481
+
482
+ .vta-detail-flags {
483
+ display: flex;
484
+ gap: 0.5rem;
485
+ flex-wrap: wrap;
486
+ }
487
+
488
+ .vta-detail-flag {
489
+ display: inline-flex;
490
+ align-items: center;
491
+ gap: 0.35rem;
492
+ padding: 0.25rem 0.65rem;
493
+ border-radius: 999px;
494
+ font-size: 0.8rem;
495
+ font-weight: 500;
496
+ background: #d1fae5;
497
+ color: #065f46;
498
+ }
499
+
500
+ /* ── Loading / error states ─────────────────────────────────────── */
501
+
502
+ .vta-loading {
503
+ display: flex;
504
+ align-items: center;
505
+ justify-content: center;
506
+ height: 16rem;
507
+ color: #9ca3af;
508
+ font-size: 1rem;
509
+ }
510
+
511
+ .vta-error {
512
+ padding: 1.5rem;
513
+ color: #ef4444;
514
+ font-size: 0.95rem;
515
+ }
516
+
517
+ /* ── Responsive ─────────────────────────────────────────────────── */
518
+
519
+ @media (max-width: 768px) {
520
+ .vta-root { padding: 1.75rem 1.25rem; }
521
+ .vta-hero { flex-direction: column; padding: 1.5rem 1.35rem; }
522
+ .vta-hero-panel { max-width: 100%; width: 100%; }
523
+ }
524
+
525
+ /* ── Dark mode ──────────────────────────────────────────────────── */
526
+
527
+ @media (prefers-color-scheme: dark) {
528
+ .vta-root { color: #e5e7eb; }
529
+
530
+ .vta-hero {
531
+ background: linear-gradient(135deg, rgba(15, 23, 42, 0.98), rgba(15, 23, 42, 0.92));
532
+ border-color: rgba(148, 163, 184, 0.45);
533
+ box-shadow:
534
+ 0 24px 60px rgba(15, 23, 42, 0.85),
535
+ 0 0 0 1px rgba(15, 23, 42, 0.75);
536
+ }
537
+
538
+ .vta-hero-eyebrow { color: #9ca3af; }
539
+ .vta-hero-title { color: #f9fafb; }
540
+ .vta-hero-tagline { color: #cbd5f5; }
541
+ .vta-hero-summary { color: #9ca3af; }
542
+
543
+ .vta-badge {
544
+ background: rgba(15, 23, 42, 0.95);
545
+ border-color: rgba(148, 163, 184, 0.45);
546
+ }
547
+
548
+ .vta-endpoint-label { color: #93c5fd; }
549
+
550
+ .vta-endpoint-box {
551
+ background: rgba(31, 41, 55, 0.95);
552
+ border-color: rgba(148, 163, 184, 0.6);
553
+ }
554
+
555
+ .vta-endpoint-code { color: #e5e7eb; }
556
+
557
+ .vta-copy-btn {
558
+ background: rgba(55, 65, 81, 0.95);
559
+ color: #e5e7eb;
560
+ }
561
+ .vta-copy-btn:hover {
562
+ background: rgba(75, 85, 99, 0.98);
563
+ color: #f9fafb;
564
+ }
565
+
566
+ .vta-hero-hint { color: #9ca3af; }
567
+ .vta-hero-hint strong { color: #e5e7eb; }
568
+
569
+ .vta-search-input {
570
+ background: rgba(15, 23, 42, 0.96);
571
+ border-color: rgba(55, 65, 81, 0.9);
572
+ color: #e5e7eb;
573
+ box-shadow:
574
+ 0 6px 16px rgba(15, 23, 42, 0.9),
575
+ 0 0 0 1px rgba(15, 23, 42, 0.9);
576
+ }
577
+ .vta-search-input::placeholder { color: #6b7280; }
578
+ .vta-search-input:focus {
579
+ border-color: #60a5fa;
580
+ box-shadow:
581
+ 0 0 0 1px rgba(59, 130, 246, 0.7),
582
+ 0 10px 26px rgba(30, 64, 175, 0.7);
583
+ }
584
+
585
+ .vta-search-hint { color: #9ca3af; }
586
+ .vta-divider { border-top-color: rgba(148, 163, 184, 0.4); }
587
+ .vta-section-title { color: #e5e7eb; }
588
+
589
+ .vta-card {
590
+ background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),
591
+ rgba(15, 23, 42, 0.9);
592
+ box-shadow:
593
+ 0 14px 30px rgba(15, 23, 42, 0.8),
594
+ 0 0 0 1px rgba(15, 23, 42, 0.85);
595
+ border-color: rgba(148, 163, 184, 0.5);
596
+ }
597
+ .vta-card:hover {
598
+ box-shadow:
599
+ 0 18px 40px rgba(15, 23, 42, 0.9),
600
+ 0 0 0 1px rgba(59, 130, 246, 0.8);
601
+ }
602
+
603
+ .vta-card-title { color: #e5e7eb; }
604
+ .vta-card-desc { color: #9ca3af; }
605
+ .vta-card-url { color: #6b7280; }
606
+
607
+ .vta-card-type--tool { background: rgba(59, 130, 246, 0.15); color: #93c5fd; }
608
+ .vta-card-type--skill { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
609
+ .vta-card-type--interaction { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
610
+ .vta-card-type--type { background: rgba(107, 114, 128, 0.2); color: #d1d5db; }
611
+ .vta-card-type--template { background: rgba(139, 92, 246, 0.15); color: #c4b5fd; }
612
+ .vta-card-type--mcp { background: rgba(236, 72, 153, 0.15); color: #f9a8d4; }
613
+
614
+ .vta-tag {
615
+ background: rgba(250, 204, 21, 0.12);
616
+ color: #facc15;
617
+ }
618
+
619
+ /* Detail page dark mode */
620
+ .vta-detail-back { color: #60a5fa; }
621
+
622
+ .vta-detail-title { color: #f9fafb; }
623
+ .vta-detail-desc { color: #cbd5e1; }
624
+
625
+ .vta-detail-section h2 { color: #e5e7eb; }
626
+
627
+ .vta-detail-card {
628
+ background: rgba(15, 23, 42, 0.9);
629
+ border-color: rgba(148, 163, 184, 0.5);
630
+ }
631
+
632
+ .vta-detail-role--system { background: rgba(59, 130, 246, 0.15); color: #93c5fd; }
633
+ .vta-detail-role--user { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
634
+ .vta-detail-role--assistant { background: rgba(139, 92, 246, 0.15); color: #c4b5fd; }
635
+ .vta-detail-role--safety { background: rgba(236, 72, 153, 0.15); color: #f9a8d4; }
636
+ .vta-detail-role--tool { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
637
+
638
+ .vta-detail-prompt-name { color: #9ca3af; }
639
+
640
+ .vta-detail-code {
641
+ background: rgba(15, 23, 42, 0.95);
642
+ border-color: rgba(148, 163, 184, 0.4);
643
+ color: #e5e7eb;
644
+ }
645
+
646
+ .vta-detail-flag {
647
+ background: rgba(16, 185, 129, 0.15);
648
+ color: #6ee7b7;
649
+ }
650
+ }
@@ -0,0 +1,23 @@
1
+ import { NavLink } from '@vertesia/ui/router';
2
+ import type { CollectionInfo } from '../types.js';
3
+
4
+ export function CollectionCard({ collection }: { collection: CollectionInfo }) {
5
+ const href = `/${collection.type}s/${collection.name}`;
6
+
7
+ return (
8
+ <NavLink href={href} className="vta-card-link">
9
+ <div className="vta-card vta-card--link">
10
+ <span className={`vta-card-type vta-card-type--${collection.type}`}>
11
+ {collection.type}
12
+ </span>
13
+ <div className="vta-card-title">{collection.title}</div>
14
+ <div className="vta-card-desc">
15
+ {collection.description || 'No description'}
16
+ </div>
17
+ <div className="vta-card-url">
18
+ {collection.count} {collection.count === 1 ? 'item' : 'items'}
19
+ </div>
20
+ </div>
21
+ </NavLink>
22
+ );
23
+ }
@@ -0,0 +1,40 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ResourceType } from '../types.js';
3
+ import { NavLink } from '@vertesia/ui/router';
4
+
5
+ interface DetailPageProps {
6
+ type: ResourceType;
7
+ title: string;
8
+ description?: string;
9
+ tags?: string[];
10
+ backHref?: string;
11
+ children?: ReactNode;
12
+ }
13
+
14
+ export function DetailPage({ type, title, description, tags, backHref = '/', children }: DetailPageProps) {
15
+ return (
16
+ <div className="vta-root">
17
+ <nav className="vta-detail-nav">
18
+ {backHref !== '/' && (
19
+ <NavLink href="/" className="vta-detail-back">Home</NavLink>
20
+ )}
21
+ <NavLink href={backHref} className="vta-detail-back">&larr; Back</NavLink>
22
+ </nav>
23
+
24
+ <div className="vta-detail-header">
25
+ <span className={`vta-card-type vta-card-type--${type}`}>{type}</span>
26
+ <h1 className="vta-detail-title">{title}</h1>
27
+ {description && <p className="vta-detail-desc">{description}</p>}
28
+ {tags && tags.length > 0 && (
29
+ <div className="vta-card-tags">
30
+ {tags.map(tag => (
31
+ <span key={tag} className="vta-tag">{tag}</span>
32
+ ))}
33
+ </div>
34
+ )}
35
+ </div>
36
+
37
+ {children}
38
+ </div>
39
+ );
40
+ }