@kyro-cms/admin 0.3.2 → 0.3.4

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 (242) hide show
  1. package/dist/EditorClient-XEUOVAAC.js +466 -0
  2. package/dist/EditorClient-XEUOVAAC.js.map +1 -0
  3. package/dist/EditorClient-YLCGVDXY.cjs +468 -0
  4. package/dist/EditorClient-YLCGVDXY.cjs.map +1 -0
  5. package/dist/chunk-7KPIUCGT.js +384 -0
  6. package/dist/chunk-7KPIUCGT.js.map +1 -0
  7. package/dist/chunk-GOACG6R7.cjs +473 -0
  8. package/dist/chunk-GOACG6R7.cjs.map +1 -0
  9. package/dist/index.cjs +14861 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.css +1661 -0
  12. package/dist/index.css.map +1 -0
  13. package/dist/index.d.ts +563 -0
  14. package/dist/index.js +14784 -0
  15. package/dist/index.js.map +1 -0
  16. package/package.json +19 -19
  17. package/src/components/ActionBar.tsx +7 -43
  18. package/src/components/Admin.tsx +138 -277
  19. package/src/components/ApiKeysManager.tsx +428 -419
  20. package/src/components/AuditLogsPage.tsx +35 -39
  21. package/src/components/AuthBridge.tsx +51 -0
  22. package/src/components/AutoForm.tsx +495 -1230
  23. package/src/components/BrandingHub.tsx +18 -19
  24. package/src/components/BulkActionsBar.tsx +1 -1
  25. package/src/components/CreateView.tsx +22 -36
  26. package/src/components/Dashboard.tsx +60 -84
  27. package/src/components/DetailView.tsx +113 -91
  28. package/src/components/DeveloperCenter.tsx +200 -198
  29. package/src/components/FieldRenderer.tsx +206 -0
  30. package/src/components/GraphQLPlayground.tsx +340 -480
  31. package/src/components/ListView.tsx +828 -254
  32. package/src/components/LoginPage.tsx +3 -4
  33. package/src/components/MarketplaceManager.tsx +254 -0
  34. package/src/components/MediaGallery.tsx +856 -1192
  35. package/src/components/PluginsManager.tsx +277 -0
  36. package/src/components/RestPlayground.tsx +398 -560
  37. package/src/components/SessionsManager.tsx +211 -0
  38. package/src/components/Sidebar.astro +179 -151
  39. package/src/components/ThemeProvider.tsx +7 -161
  40. package/src/components/UserManagement.tsx +162 -146
  41. package/src/components/UserMenu.tsx +110 -0
  42. package/src/components/WebhookManager.tsx +305 -367
  43. package/src/components/blocks/AccordionBlock.tsx +4 -4
  44. package/src/components/blocks/ArrayBlock.tsx +3 -3
  45. package/src/components/blocks/BlockEditModal.tsx +8 -8
  46. package/src/components/blocks/BlockWrapper.tsx +61 -0
  47. package/src/components/blocks/ButtonBlock.tsx +4 -4
  48. package/src/components/blocks/ChildBlocksTree.tsx +23 -25
  49. package/src/components/blocks/CodeBlock.tsx +15 -15
  50. package/src/components/blocks/ColumnsBlock.tsx +6 -44
  51. package/src/components/blocks/DividerBlock.tsx +3 -3
  52. package/src/components/blocks/FileBlock.tsx +4 -4
  53. package/src/components/blocks/HeadingBlock.tsx +6 -38
  54. package/src/components/blocks/HeroBlock.tsx +4 -4
  55. package/src/components/blocks/ImageBlock.tsx +4 -4
  56. package/src/components/blocks/LinkBlock.tsx +4 -4
  57. package/src/components/blocks/ListBlock.tsx +3 -3
  58. package/src/components/blocks/ParagraphBlock.tsx +12 -42
  59. package/src/components/blocks/RelationshipBlock.tsx +4 -4
  60. package/src/components/blocks/RichTextBlock.tsx +4 -4
  61. package/src/components/blocks/VStackBlock.tsx +5 -37
  62. package/src/components/blocks/VideoBlock.tsx +4 -4
  63. package/src/components/blocks/types.ts +11 -0
  64. package/src/components/fields/AccordionField.tsx +1 -1
  65. package/src/components/fields/ArrayField.tsx +2 -2
  66. package/src/components/fields/ArrayLayout.tsx +93 -0
  67. package/src/components/fields/BlocksField.tsx +122 -111
  68. package/src/components/fields/ButtonField.tsx +1 -1
  69. package/src/components/fields/CheckboxField.tsx +14 -15
  70. package/src/components/fields/ChildrenField.tsx +2 -2
  71. package/src/components/fields/CodeField.tsx +3 -3
  72. package/src/components/fields/ColumnsField.tsx +2 -2
  73. package/src/components/fields/DateField.tsx +13 -26
  74. package/src/components/fields/EditorClient.tsx +26 -28
  75. package/src/components/fields/FieldLayout.tsx +52 -0
  76. package/src/components/fields/GroupLayout.tsx +35 -0
  77. package/src/components/fields/JSONField.tsx +7 -7
  78. package/src/components/fields/LinkField.tsx +1 -1
  79. package/src/components/fields/MarkdownField.tsx +1 -1
  80. package/src/components/fields/NumberField.tsx +13 -26
  81. package/src/components/fields/PortableTextField.tsx +4 -4
  82. package/src/components/fields/PortableTextRenderer.tsx +1 -1
  83. package/src/components/fields/RelationshipBlockField.tsx +31 -23
  84. package/src/components/fields/RelationshipField.tsx +14 -14
  85. package/src/components/fields/SelectField.tsx +17 -26
  86. package/src/components/fields/TabsLayout.tsx +69 -0
  87. package/src/components/fields/TextField.tsx +85 -38
  88. package/src/components/fields/UploadField.tsx +71 -41
  89. package/src/components/fields/VideoField.tsx +1 -1
  90. package/src/components/fields/extensions/blockComponents.tsx +2 -2
  91. package/src/components/fields/extensions/blocksStore.ts +207 -193
  92. package/src/components/fields/types.ts +22 -0
  93. package/src/components/layout/Layout.tsx +1 -1
  94. package/src/components/ui/ActionMenu.tsx +63 -0
  95. package/src/components/ui/Badge.tsx +59 -5
  96. package/src/components/ui/BlockDrawer.tsx +4 -5
  97. package/src/components/ui/CommandPalette.tsx +58 -36
  98. package/src/components/ui/CommandPaletteWrapper.tsx +18 -17
  99. package/src/components/ui/Dropdown.tsx +18 -16
  100. package/src/components/ui/EmptyState.tsx +25 -0
  101. package/src/components/ui/GlobalModal.tsx +49 -0
  102. package/src/components/ui/IconButton.tsx +44 -0
  103. package/src/components/ui/Modal.tsx +19 -20
  104. package/src/components/ui/PageHeader.tsx +158 -0
  105. package/src/components/ui/Pagination.tsx +61 -0
  106. package/src/components/ui/PromptModal.tsx +1 -1
  107. package/src/components/ui/SearchInput.tsx +57 -0
  108. package/src/components/ui/SeoPreview.tsx +31 -0
  109. package/src/components/ui/SessionModal.tsx +0 -0
  110. package/src/components/ui/SlidePanel.tsx +2 -0
  111. package/src/components/ui/Toast.tsx +65 -122
  112. package/src/components/ui/Toaster.tsx +18 -0
  113. package/src/components/ui/icons.tsx +112 -0
  114. package/src/components/users/UserDetail.tsx +290 -0
  115. package/src/components/users/UserForm.tsx +242 -0
  116. package/src/components/users/UsersList.tsx +338 -0
  117. package/src/env.d.ts +13 -13
  118. package/src/fields/index.ts +2 -1
  119. package/src/global.d.ts +7 -0
  120. package/src/hooks/data.ts +2 -9
  121. package/src/hooks/useAsyncData.ts +36 -0
  122. package/src/hooks/useAutoFormState.ts +527 -0
  123. package/src/hooks/useSelection.ts +49 -0
  124. package/src/hooks/useSession.ts +0 -0
  125. package/src/index.ts +11 -1
  126. package/src/integration.ts +86 -11
  127. package/src/kyro-cms.d.ts +209 -0
  128. package/src/layouts/AdminLayout.astro +128 -11
  129. package/src/layouts/AuthLayout.astro +21 -5
  130. package/src/lib/api.ts +175 -55
  131. package/src/lib/autoform-store.ts +435 -0
  132. package/src/lib/config.ts +82 -34
  133. package/src/lib/createRegistry.ts +29 -0
  134. package/src/lib/default-kyro-config.ts +4 -0
  135. package/src/lib/globals.ts +50 -0
  136. package/src/lib/media-utils.ts +18 -0
  137. package/src/lib/object-utils.ts +77 -0
  138. package/src/lib/paths.ts +61 -0
  139. package/src/lib/stores/index.ts +370 -0
  140. package/src/lib/types.ts +43 -0
  141. package/src/lib/useResourceManager.ts +105 -0
  142. package/src/pages/403.astro +67 -0
  143. package/src/pages/[collection]/[id].astro +14 -180
  144. package/src/pages/[collection]/index.astro +11 -6
  145. package/src/pages/api-explorer.astro +173 -0
  146. package/src/pages/audit/index.astro +2 -0
  147. package/src/pages/auth/login.astro +122 -0
  148. package/src/pages/auth/register.astro +167 -0
  149. package/src/pages/graphql-explorer.astro +59 -0
  150. package/src/pages/{admin/graphql.astro → graphql.astro} +51 -17
  151. package/src/pages/index.astro +577 -0
  152. package/src/pages/index_ALT.astro +3 -0
  153. package/src/pages/keys.astro +11 -0
  154. package/src/pages/marketplace.astro +11 -0
  155. package/src/pages/media.astro +3 -0
  156. package/src/pages/plugins.astro +8 -0
  157. package/src/pages/preview/[collection]/[id].astro +188 -123
  158. package/src/pages/rest-playground.astro +62 -0
  159. package/src/pages/roles/index.astro +183 -76
  160. package/src/pages/sessions.astro +8 -0
  161. package/src/pages/settings/[slug].astro +92 -114
  162. package/src/pages/settings/index.astro +5 -3
  163. package/src/pages/users/[id].astro +25 -154
  164. package/src/pages/users/index.astro +19 -130
  165. package/src/pages/users/new.astro +9 -86
  166. package/src/pages/webhooks.astro +11 -0
  167. package/src/routes.ts +80 -0
  168. package/src/styles/main.css +119 -79
  169. package/src/theme/tokens.ts +1 -0
  170. package/src/vite-env.d.ts +14 -0
  171. package/src/collections/auth/index.ts +0 -155
  172. package/src/collections/portfolio/index.ts +0 -343
  173. package/src/components/ApiExplorer.tsx +0 -325
  174. package/src/components/EnhancedListView.tsx +0 -889
  175. package/src/components/GraphQLExplorer.tsx +0 -675
  176. package/src/components/Icons.tsx +0 -23
  177. package/src/components/StatusBadge.tsx +0 -76
  178. package/src/lib/MediaService.ts +0 -541
  179. package/src/lib/auth/sqlite-adapter.ts +0 -319
  180. package/src/lib/dataStore.ts +0 -226
  181. package/src/lib/db/adapter.ts +0 -54
  182. package/src/lib/db/drizzle-mysql-adapter.ts +0 -194
  183. package/src/lib/db/drizzle-mysql-auth-adapter.ts +0 -327
  184. package/src/lib/db/drizzle-postgres-adapter.ts +0 -202
  185. package/src/lib/db/drizzle-postgres-auth-adapter.ts +0 -304
  186. package/src/lib/db/drizzle-sqlite-adapter.ts +0 -227
  187. package/src/lib/db/drizzle-sqlite-auth-adapter.ts +0 -548
  188. package/src/lib/db/index.ts +0 -449
  189. package/src/lib/db/mongodb-adapter.ts +0 -207
  190. package/src/lib/db/mongodb-auth-adapter.ts +0 -305
  191. package/src/lib/db/schema/mysql-auth.ts +0 -113
  192. package/src/lib/db/schema/mysql-content.ts +0 -20
  193. package/src/lib/db/schema/postgres-auth.ts +0 -116
  194. package/src/lib/db/schema/postgres-content.ts +0 -35
  195. package/src/lib/db/schema/postgres-media.ts +0 -52
  196. package/src/lib/db/schema/postgres-settings.ts +0 -11
  197. package/src/lib/db/schema/sqlite-auth.ts +0 -112
  198. package/src/lib/db/schema/sqlite-content.ts +0 -20
  199. package/src/lib/db/version-adapter.ts +0 -248
  200. package/src/lib/graphql/index.ts +0 -1
  201. package/src/lib/graphql/schema.ts +0 -443
  202. package/src/lib/rate-limit.ts +0 -267
  203. package/src/lib/storage.ts +0 -374
  204. package/src/lib/store.ts +0 -85
  205. package/src/middleware.ts +0 -177
  206. package/src/pages/admin/api-explorer.astro +0 -98
  207. package/src/pages/admin/graphql-explorer.astro +0 -40
  208. package/src/pages/admin/index.astro +0 -286
  209. package/src/pages/admin/keys.astro +0 -8
  210. package/src/pages/admin/rest-playground.astro +0 -44
  211. package/src/pages/admin/webhooks.astro +0 -8
  212. package/src/pages/api/[collection]/[id]/publish.ts +0 -52
  213. package/src/pages/api/[collection]/[id]/unpublish.ts +0 -42
  214. package/src/pages/api/[collection]/[id]/versions.ts +0 -66
  215. package/src/pages/api/[collection]/[id].ts +0 -213
  216. package/src/pages/api/[collection]/index.ts +0 -209
  217. package/src/pages/api/auth/[id].ts +0 -121
  218. package/src/pages/api/auth/audit-logs.ts +0 -57
  219. package/src/pages/api/auth/login.ts +0 -211
  220. package/src/pages/api/auth/logout.ts +0 -66
  221. package/src/pages/api/auth/me.ts +0 -36
  222. package/src/pages/api/auth/refresh.ts +0 -119
  223. package/src/pages/api/auth/register.ts +0 -188
  224. package/src/pages/api/auth/users.ts +0 -97
  225. package/src/pages/api/collections.ts +0 -59
  226. package/src/pages/api/globals/[slug].ts +0 -42
  227. package/src/pages/api/graphql.ts +0 -90
  228. package/src/pages/api/health.ts +0 -426
  229. package/src/pages/api/keys/[id].ts +0 -26
  230. package/src/pages/api/keys/index.ts +0 -75
  231. package/src/pages/api/media/[id].ts +0 -309
  232. package/src/pages/api/media/folders.ts +0 -609
  233. package/src/pages/api/media/index.ts +0 -146
  234. package/src/pages/api/media/resize.ts +0 -267
  235. package/src/pages/api/search.ts +0 -82
  236. package/src/pages/api/slug-availability.ts +0 -70
  237. package/src/pages/api/storage-config.ts +0 -20
  238. package/src/pages/api/storage-status.ts +0 -206
  239. package/src/pages/api/upload.ts +0 -334
  240. package/src/pages/api/webhooks/index.ts +0 -71
  241. package/src/pages/login.astro +0 -82
  242. package/src/pages/register.astro +0 -102
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect, useCallback } from "react";
2
- import { apiGet } from "../lib/api";
2
+ import { fetchWithAuth } from "../lib/api";
3
3
  import { Modal } from "./ui/Modal";
4
4
 
5
5
  interface AuditLog {
@@ -143,7 +143,7 @@ function MetadataRow({ label, value }: { label: string; value: unknown }) {
143
143
  typeof value === "object" ? JSON.stringify(value) : String(value);
144
144
  return (
145
145
  <div className="flex items-start gap-3 py-2 px-4 border-b border-[var(--kyro-border)] last:border-0 bg-[var(--kyro-surface-accent)]">
146
- <span className="text-[10px] font-bold uppercase tracking-wider text-[var(--kyro-text-muted)] w-24 shrink-0 pt-0.5">
146
+ <span className="text-[10px] font-bold tracking-wider text-[var(--kyro-text-muted)] w-24 shrink-0 pt-0.5">
147
147
  {label}
148
148
  </span>
149
149
  <span className="text-xs font-mono text-[var(--kyro-text-primary)] break-all">
@@ -177,7 +177,7 @@ export function AuditLogsPage() {
177
177
  if (action) params.set("action", action);
178
178
  if (successFilter) params.set("success", successFilter);
179
179
 
180
- const res = await fetch(`/api/auth/audit-logs?${params}`);
180
+ const res = await fetchWithAuth(`/api/auth/audit-logs?${params}`);
181
181
  if (!res.ok) throw new Error("Failed to fetch");
182
182
  const data: AuditLogsResponse = await res.json();
183
183
  setLogs(data.docs);
@@ -206,11 +206,11 @@ export function AuditLogsPage() {
206
206
  };
207
207
 
208
208
  return (
209
- <div className="flex-1 overflow-y-auto p-8 pr-12 space-y-6">
209
+ <div className="flex-1 overflow-y-auto pr-12 space-y-6">
210
210
  {/* Header */}
211
211
  <div className="surface-tile p-6 flex items-center justify-between gap-8">
212
212
  <div>
213
- <h1 className="text-3xl font-black tracking-tighter text-[var(--kyro-text-primary)]">
213
+ <h1 className="text-xl font-bold tracking-tighter text-[var(--kyro-text-primary)]">
214
214
  Audit Logs
215
215
  </h1>
216
216
  <p className="text-sm text-[var(--kyro-text-secondary)] mt-1 font-medium">
@@ -320,8 +320,8 @@ export function AuditLogsPage() {
320
320
  },
321
321
  ].map(({ label, value, color }) => (
322
322
  <div key={label} className="surface-tile p-4">
323
- <div className={`text-2xl font-black ${color}`}>{value}</div>
324
- <div className="text-[10px] font-bold text-[var(--kyro-text-secondary)] uppercase tracking-wider mt-1">
323
+ <div className={`text-2xl font-bold ${color}`}>{value}</div>
324
+ <div className="text-[10px] font-bold text-[var(--kyro-text-secondary)] tracking-wider mt-1">
325
325
  {label}
326
326
  </div>
327
327
  </div>
@@ -358,7 +358,7 @@ export function AuditLogsPage() {
358
358
  />
359
359
  </svg>
360
360
  </div>
361
- <p className="font-bold text-[var(--kyro-text-primary)] text-base">
361
+ <p className="font-medium text-[var(--kyro-text-primary)] text-base">
362
362
  No audit logs found
363
363
  </p>
364
364
  <p className="text-sm text-[var(--kyro-text-secondary)]">
@@ -371,7 +371,7 @@ export function AuditLogsPage() {
371
371
  ) : (
372
372
  <table className="w-full text-left">
373
373
  <thead>
374
- <tr className="text-[var(--kyro-text-secondary)] font-bold text-[10px] uppercase tracking-[0.2em] border-b border-[var(--kyro-border)]">
374
+ <tr className="text-[var(--kyro-text-secondary)] font-bold text-[10px] tracking-[0.2em] border-b border-[var(--kyro-border)]">
375
375
  <th className="px-6 py-5 w-8"></th>
376
376
  <th className="px-6 py-5">Action</th>
377
377
  <th className="px-6 py-5">User</th>
@@ -405,16 +405,16 @@ export function AuditLogsPage() {
405
405
  {log.userEmail ? (
406
406
  <div className="flex items-center gap-2.5">
407
407
  <div
408
- className={`w-7 h-7 rounded-lg ${getAvatarColor(log.userEmail)} text-[var(--kyro-text-primary)] text-[10px] font-black flex items-center justify-center shrink-0`}
408
+ className={`w-7 h-7 rounded-lg ${getAvatarColor(log.userEmail)} text-[var(--kyro-text-primary)] text-[10px] font-bold flex items-center justify-center shrink-0`}
409
409
  >
410
410
  {getInitials(log.userEmail)}
411
411
  </div>
412
412
  <div>
413
- <div className="text-sm font-bold text-[var(--kyro-text-primary)] leading-none">
413
+ <div className="text-sm font-medium text-[var(--kyro-text-primary)] leading-none">
414
414
  {log.userEmail.split("@")[0]}
415
415
  </div>
416
416
  {log.role && (
417
- <div className="text-[10px] font-bold text-[var(--kyro-text-muted)] mt-0.5 uppercase tracking-wider">
417
+ <div className="text-[10px] font-bold text-[var(--kyro-text-muted)] mt-0.5 tracking-wider">
418
418
  {log.role}
419
419
  </div>
420
420
  )}
@@ -427,7 +427,7 @@ export function AuditLogsPage() {
427
427
  )}
428
428
  </td>
429
429
  <td className="px-6 py-4">
430
- <div className="text-sm font-bold text-[var(--kyro-text-primary)]">
430
+ <div className="text-sm font-medium text-[var(--kyro-text-primary)]">
431
431
  {log.resource}
432
432
  </div>
433
433
  {log.resourceId && (
@@ -497,11 +497,10 @@ export function AuditLogsPage() {
497
497
  type="button"
498
498
  onClick={() => fetchLogs(page - 1)}
499
499
  disabled={page <= 1}
500
- className={`px-4 py-2 rounded-xl text-sm font-bold transition-all ${
501
- page <= 1
502
- ? "opacity-30 pointer-events-none text-[var(--kyro-text-muted)]"
503
- : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
504
- }`}
500
+ className={`px-4 py-2 rounded-xl text-sm font-bold transition-all ${page <= 1
501
+ ? "opacity-30 pointer-events-none text-[var(--kyro-text-muted)]"
502
+ : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
503
+ }`}
505
504
  >
506
505
  ← Prev
507
506
  </button>
@@ -512,11 +511,10 @@ export function AuditLogsPage() {
512
511
  type="button"
513
512
  key={p}
514
513
  onClick={() => fetchLogs(p)}
515
- className={`px-3.5 py-2 rounded-xl text-sm font-bold transition-all ${
516
- p === page
517
- ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)]"
518
- : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
519
- }`}
514
+ className={`px-3.5 py-2 rounded-xl text-sm font-bold transition-all ${p === page
515
+ ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)]"
516
+ : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
517
+ }`}
520
518
  >
521
519
  {p}
522
520
  </button>
@@ -526,11 +524,10 @@ export function AuditLogsPage() {
526
524
  type="button"
527
525
  onClick={() => fetchLogs(page + 1)}
528
526
  disabled={page >= totalPages}
529
- className={`px-4 py-2 rounded-xl text-sm font-bold transition-all ${
530
- page >= totalPages
531
- ? "opacity-30 pointer-events-none text-[var(--kyro-text-muted)]"
532
- : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
533
- }`}
527
+ className={`px-4 py-2 rounded-xl text-sm font-bold transition-all ${page >= totalPages
528
+ ? "opacity-30 pointer-events-none text-[var(--kyro-text-muted)]"
529
+ : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface)] border border-[var(--kyro-border)]"
530
+ }`}
534
531
  >
535
532
  Next →
536
533
  </button>
@@ -549,18 +546,17 @@ export function AuditLogsPage() {
549
546
  <div className="space-y-0">
550
547
  {/* Status banner */}
551
548
  <div
552
- className={`-mx-6 -mt-4 px-6 py-4 mb-6 rounded-t-xl flex items-center gap-3 ${
553
- selectedLog.success
554
- ? "bg-green-500/5 border-b border-green-500/10"
555
- : "bg-red-500/5 border-b border-red-500/10"
556
- }`}
549
+ className={`px-4 py-4 mb-6 rounded-lg flex items-center gap-3 ${selectedLog.success
550
+ ? "bg-green-500/5 border-b border-green-500/10"
551
+ : "bg-red-500/5 border-b border-red-500/10"
552
+ }`}
557
553
  >
558
554
  <span
559
555
  className={`w-2.5 h-2.5 rounded-full shrink-0 ${selectedLog.success ? "bg-green-500" : "bg-red-500"}`}
560
556
  />
561
557
  <div>
562
558
  <div
563
- className={`text-sm font-black ${selectedLog.success ? "text-green-500" : "text-red-500"}`}
559
+ className={`text-sm font-bold ${selectedLog.success ? "text-green-500" : "text-red-500"}`}
564
560
  >
565
561
  {selectedLog.success ? "Successful" : "Failed"}
566
562
  </div>
@@ -586,7 +582,7 @@ export function AuditLogsPage() {
586
582
  {/* Error message */}
587
583
  {selectedLog.error && (
588
584
  <div className="mt-4 -mx-6 px-6 py-4 bg-red-500/5 border-y border-red-500/10">
589
- <div className="text-[10px] font-bold uppercase tracking-wider text-red-400 mb-2">
585
+ <div className="text-[10px] font-bold tracking-wider text-red-400 mb-2">
590
586
  Error
591
587
  </div>
592
588
  <div className="text-sm font-mono text-red-300">
@@ -598,7 +594,7 @@ export function AuditLogsPage() {
598
594
  {/* Changes */}
599
595
  {selectedLog.changes && selectedLog.changes.length > 0 && (
600
596
  <div className="mt-4">
601
- <div className="text-[10px] font-bold uppercase tracking-wider text-[var(--kyro-text-muted)] mb-3">
597
+ <div className="text-[10px] font-bold tracking-wider text-[var(--kyro-text-muted)] mb-3">
602
598
  Changes ({selectedLog.changes.length})
603
599
  </div>
604
600
  <div className="rounded-xl border border-[var(--kyro-border)] overflow-hidden">
@@ -607,7 +603,7 @@ export function AuditLogsPage() {
607
603
  key={i}
608
604
  className="flex items-start gap-4 px-4 py-3 text-xs font-mono border-b border-[var(--kyro-border)] last:border-0 hover:bg-[var(--kyro-surface-accent)] transition-colors"
609
605
  >
610
- <span className="text-[10px] font-bold uppercase tracking-wider text-[var(--kyro-text-muted)] w-24 shrink-0 pt-0.5">
606
+ <span className="text-[10px] font-bold tracking-wider text-[var(--kyro-text-muted)] w-24 shrink-0 pt-0.5">
611
607
  {change.field}
612
608
  </span>
613
609
  <span className="text-red-400 line-through flex-1 truncate">
@@ -633,7 +629,7 @@ export function AuditLogsPage() {
633
629
  {selectedLog.metadata &&
634
630
  Object.keys(selectedLog.metadata).length > 0 && (
635
631
  <div className="mt-4">
636
- <div className="text-[10px] font-bold uppercase tracking-wider text-[var(--kyro-text-muted)] mb-3">
632
+ <div className="text-[10px] font-bold tracking-wider text-[var(--kyro-text-muted)] mb-3">
637
633
  Metadata
638
634
  </div>
639
635
  <div className="border border-[var(--kyro-border)] overflow-hidden">
@@ -653,7 +649,7 @@ export function AuditLogsPage() {
653
649
  {/* User Agent */}
654
650
  {selectedLog.userAgent && (
655
651
  <div className="mt-4">
656
- <div className="text-[10px] font-bold uppercase tracking-wider text-[var(--kyro-text-muted)] mb-2">
652
+ <div className="text-[10px] font-bold tracking-wider text-[var(--kyro-text-muted)] mb-2">
657
653
  User Agent
658
654
  </div>
659
655
  <div className="text-xs font-mono text-[var(--kyro-text-secondary)] bg-[var(--kyro-bg-secondary)] rounded-lg px-3 py-2 border border-[var(--kyro-border)]">
@@ -0,0 +1,51 @@
1
+ import { useEffect } from "react";
2
+ import { useAuthStore } from "../lib/stores";
3
+
4
+ /**
5
+ * AuthBridge
6
+ *
7
+ * This component is the critical link between the vanilla-JS auth flow
8
+ * (which runs in AdminLayout.astro and fires `kyro:auth-ready`) and the
9
+ * React Zustand store (`useAuthStore`).
10
+ *
11
+ * It:
12
+ * 1. Checks `window.__kyroAuth` immediately in case the event already fired
13
+ * before this component mounted (race condition on fast networks).
14
+ * 2. Listens for the `kyro:auth-ready` custom event and populates the store.
15
+ *
16
+ * Once the store is hydrated, every React component that calls
17
+ * `useAuthStore()` will automatically re-render with the correct permissions.
18
+ */
19
+ export function AuthBridge() {
20
+ const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
21
+
22
+ useEffect(() => {
23
+ const { setUser, setLoading } = useAuthStore.getState();
24
+
25
+ function populate(detail: { user: unknown; permissions: unknown }) {
26
+ if (detail?.user) {
27
+ setUser(detail.user, detail.permissions ?? null);
28
+ } else {
29
+ // Unauthenticated – set loading to false so components don't hang
30
+ setLoading(false);
31
+ }
32
+ }
33
+
34
+ // Check if the event already fired before this component mounted
35
+ const cached = (window as { __kyroAuth?: { user: unknown; permissions: unknown; verified: boolean } }).__kyroAuth;
36
+ if (cached?.verified && cached?.user) {
37
+ populate({ user: cached.user, permissions: cached.permissions ?? null });
38
+ return; // No need to register the event listener
39
+ }
40
+
41
+ // Otherwise wait for the event
42
+ const handler = (event: Event) => {
43
+ populate((event as CustomEvent).detail);
44
+ };
45
+
46
+ window.addEventListener("kyro:auth-ready", handler);
47
+ return () => window.removeEventListener("kyro:auth-ready", handler);
48
+ }, []);
49
+
50
+ return null;
51
+ }