@kyro-cms/admin 0.5.4 → 0.6.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.
- package/dist/{EditorClient-YLCGVDXY.cjs → EditorClient-Q23UXR37.cjs} +14 -14
- package/dist/{EditorClient-XEUOVAAC.js → EditorClient-T5PASFNR.js} +2 -2
- package/dist/chunk-3BGDYKTD.cjs +348 -0
- package/dist/chunk-3BGDYKTD.cjs.map +1 -0
- package/dist/chunk-EEFXLQVT.js +3 -0
- package/dist/chunk-EEFXLQVT.js.map +1 -0
- package/dist/index.cjs +462 -1020
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +13 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +271 -829
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
- package/src/components/AuditLogsPage.tsx +4 -8
- package/src/components/Dashboard.tsx +2 -1
- package/src/components/DetailView.tsx +9 -2
- package/src/components/ListView.tsx +3 -2
- package/src/components/MediaGallery.tsx +13 -6
- package/src/components/Sidebar.astro +1 -1
- package/src/components/ui/Shimmer.tsx +28 -0
- package/src/components/users/UserDetail.tsx +1 -1
- package/src/components/users/UserForm.tsx +1 -1
- package/src/components/users/UsersList.tsx +1 -1
- package/src/hooks/useAutoFormState.ts +19 -3
- package/src/integration.ts +77 -25
- package/src/layouts/AdminLayout.astro +70 -48
- package/src/lib/config.ts +6 -1
- package/src/lib/globals.ts +56 -20
- package/src/pages/index.astro +1 -1
- package/src/pages/roles/index.astro +1 -1
- package/src/pages/users/[id].astro +2 -2
- package/src/styles/main.css +17 -0
- package/dist/chunk-7KPIUCGT.js +0 -384
- package/dist/chunk-7KPIUCGT.js.map +0 -1
- package/dist/chunk-GOACG6R7.cjs +0 -473
- package/dist/chunk-GOACG6R7.cjs.map +0 -1
- /package/dist/{EditorClient-XEUOVAAC.js.map → EditorClient-Q23UXR37.cjs.map} +0 -0
- /package/dist/{EditorClient-YLCGVDXY.cjs.map → EditorClient-T5PASFNR.js.map} +0 -0
package/src/lib/globals.ts
CHANGED
|
@@ -1,24 +1,69 @@
|
|
|
1
|
-
import projectConfig from "kyro:config";
|
|
2
1
|
import type { BaseAdapter } from "../../../src/registry/types.js";
|
|
3
2
|
|
|
3
|
+
export interface GlobalOptions {
|
|
4
|
+
draft?: boolean;
|
|
5
|
+
/** Astro request object — used to pass auth cookies to the API endpoint */
|
|
6
|
+
request?: Request;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
/**
|
|
5
10
|
* Fetches a global document by its slug.
|
|
6
|
-
*
|
|
11
|
+
* Uses the API endpoint when an Astro request is provided (works for all dialects),
|
|
12
|
+
* falling back to the direct adapter approach.
|
|
7
13
|
*/
|
|
8
|
-
export async function getGlobal(slug: string, options?:
|
|
9
|
-
|
|
14
|
+
export async function getGlobal(slug: string, options?: GlobalOptions) {
|
|
15
|
+
// Strategy 1: Use the API endpoint (works for all dialects, adapter agnostic)
|
|
16
|
+
if (options?.request) {
|
|
17
|
+
try {
|
|
18
|
+
const apiPath = (globalThis as any).__KYRO_API_PATH__ || "/api";
|
|
19
|
+
const cookie = options.request.headers.get("cookie") || "";
|
|
20
|
+
const res = await fetch(`${apiPath}/globals/${slug}`, {
|
|
21
|
+
headers: { Cookie: cookie },
|
|
22
|
+
});
|
|
23
|
+
if (res.ok) {
|
|
24
|
+
const json = await res.json();
|
|
25
|
+
const doc = json.data || null;
|
|
26
|
+
if (!doc) return null;
|
|
27
|
+
// Resolve media fields via the same API endpoint
|
|
28
|
+
const mediaFields = ["siteLogo", "siteFavicon", "siteOgImage"];
|
|
29
|
+
for (const field of mediaFields) {
|
|
30
|
+
if (typeof doc[field] === "string" && doc[field].length > 0) {
|
|
31
|
+
try {
|
|
32
|
+
const mediaRes = await fetch(`${apiPath}/media/${doc[field]}`, {
|
|
33
|
+
headers: { Cookie: cookie },
|
|
34
|
+
});
|
|
35
|
+
if (mediaRes.ok) {
|
|
36
|
+
doc[field] = await mediaRes.json();
|
|
37
|
+
}
|
|
38
|
+
} catch { /* media field stays as ID string */ }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return doc;
|
|
42
|
+
}
|
|
43
|
+
} catch { /* fall through to adapter */ }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Strategy 2: Direct adapter access (fallback for non-request contexts)
|
|
47
|
+
const global = globalThis as any;
|
|
48
|
+
const projectConfig = global.__KYRO_ADMIN_PROJECT_CONFIG__;
|
|
49
|
+
if (!projectConfig) return null;
|
|
50
|
+
|
|
51
|
+
const db = projectConfig.adapter as BaseAdapter | undefined;
|
|
10
52
|
if (!db) return null;
|
|
11
53
|
|
|
12
54
|
try {
|
|
55
|
+
// Initialize adapter if needed (DrizzleAdapter needs schema/globals maps)
|
|
56
|
+
if (typeof db.init === "function" && !global.__KYRO_ADAPTER_READY__) {
|
|
57
|
+
await db.init(projectConfig.collections || [], projectConfig.globals || []);
|
|
58
|
+
global.__KYRO_ADAPTER_READY__ = true;
|
|
59
|
+
}
|
|
13
60
|
const doc = await db.findOne({
|
|
14
61
|
collection: `_globals_${slug}`,
|
|
15
62
|
where: {},
|
|
16
63
|
draft: options?.draft ?? false,
|
|
17
64
|
});
|
|
18
|
-
|
|
19
65
|
if (!doc) return null;
|
|
20
66
|
|
|
21
|
-
// Auto-resolve media IDs for common branding fields
|
|
22
67
|
const mediaFields = ["siteLogo", "siteFavicon", "siteOgImage"];
|
|
23
68
|
for (const field of mediaFields) {
|
|
24
69
|
if (typeof doc[field] === "string" && doc[field].length > 0) {
|
|
@@ -27,24 +72,15 @@ export async function getGlobal(slug: string, options?: { draft?: boolean }) {
|
|
|
27
72
|
collection: "media",
|
|
28
73
|
id: doc[field],
|
|
29
74
|
});
|
|
30
|
-
if (mediaDoc)
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
} catch (e) {
|
|
34
|
-
console.warn(`Failed to resolve media for field "${field}":`, e);
|
|
35
|
-
}
|
|
75
|
+
if (mediaDoc) doc[field] = mediaDoc;
|
|
76
|
+
} catch { /* media field stays as ID string */ }
|
|
36
77
|
}
|
|
37
78
|
}
|
|
38
|
-
|
|
39
79
|
return doc;
|
|
40
|
-
} catch
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
80
|
+
} catch { return null; }
|
|
43
81
|
}
|
|
44
82
|
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
export async function getSiteSettings(options?: { draft?: boolean }) {
|
|
83
|
+
/** Convenience helper to get the site settings. */
|
|
84
|
+
export async function getSiteSettings(options?: GlobalOptions) {
|
|
49
85
|
return await getGlobal("site-settings", options);
|
|
50
86
|
}
|
package/src/pages/index.astro
CHANGED
|
@@ -13,7 +13,7 @@ const authItems = authCollections.map((slug) => ({
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<AdminLayout title="Dashboard">
|
|
16
|
-
<div class="flex-1 overflow-y-auto
|
|
16
|
+
<div class="flex-1 overflow-y-auto space-y-8">
|
|
17
17
|
<!-- Header -->
|
|
18
18
|
<div class="surface-tile p-6 flex items-center justify-between gap-8">
|
|
19
19
|
<div class="relative flex-1 max-w-2xl">
|
|
@@ -28,7 +28,7 @@ if (id) {
|
|
|
28
28
|
|
|
29
29
|
<AdminLayout title={user ? user.email : "User"}>
|
|
30
30
|
{error ? (
|
|
31
|
-
<div class="flex-1 overflow-y-auto
|
|
31
|
+
<div class="flex-1 overflow-y-auto space-y-8">
|
|
32
32
|
<div class="surface-tile p-8">
|
|
33
33
|
<div class="text-center">
|
|
34
34
|
<p class="text-lg font-bold text-red-500">{error}</p>
|
|
@@ -44,7 +44,7 @@ if (id) {
|
|
|
44
44
|
adminPath={adminPath}
|
|
45
45
|
/>
|
|
46
46
|
) : (
|
|
47
|
-
<div class="flex-1 overflow-y-auto
|
|
47
|
+
<div class="flex-1 overflow-y-auto space-y-8">
|
|
48
48
|
<div class="surface-tile p-8 text-center">
|
|
49
49
|
<p class="text-lg font-bold text-[var(--kyro-text-secondary)]">Loading...</p>
|
|
50
50
|
</div>
|
package/src/styles/main.css
CHANGED
|
@@ -1502,6 +1502,23 @@
|
|
|
1502
1502
|
color: var(--kyro-gray-500);
|
|
1503
1503
|
}
|
|
1504
1504
|
|
|
1505
|
+
/* Shimmer Loading Effect */
|
|
1506
|
+
@keyframes shimmer {
|
|
1507
|
+
0% { background-position: -200% 0; }
|
|
1508
|
+
100% { background-position: 200% 0; }
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
.kyro-shimmer {
|
|
1512
|
+
background: linear-gradient(
|
|
1513
|
+
90deg,
|
|
1514
|
+
var(--kyro-surface-accent) 25%,
|
|
1515
|
+
var(--kyro-border) 50%,
|
|
1516
|
+
var(--kyro-surface-accent) 75%
|
|
1517
|
+
);
|
|
1518
|
+
background-size: 200% 100%;
|
|
1519
|
+
animation: shimmer 1.5s ease-in-out infinite;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1505
1522
|
/* Modal — Monochrome */
|
|
1506
1523
|
.kyro-modal-overlay {
|
|
1507
1524
|
position: fixed;
|