@brightsideoy/kama 0.1.0-alpha.170 → 0.1.0-alpha.172
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/assets/index-DAoG05nh.css +1 -0
- package/dist/assets/index-iWK1NrI-.js +164 -0
- package/dist/{dist-DkBY_SfG.js → dist-CZH1oldV.js} +223 -205
- package/dist/index.html +2 -2
- package/dist/index.js +223 -205
- package/dist/schema-compiler.js +1 -1
- package/package.json +1 -1
- package/templates/astro-starter/src/components/global/Footer.astro +63 -24
- package/templates/astro-starter/src/components/global/NavigationMenu.astro +134 -50
- package/templates/astro-starter/src/pages/[...slug].astro +1 -6
- package/dist/assets/index-CDo1UNaK.js +0 -164
- package/dist/assets/index-D5W5U152.css +0 -1
package/dist/schema-compiler.js
CHANGED
|
@@ -30,7 +30,7 @@ async function f() {
|
|
|
30
30
|
if (n(f)) l = (await import(t(f).href)).compileDefinitions;
|
|
31
31
|
else if (n(p)) l = (await import(t(p).href)).compileDefinitions;
|
|
32
32
|
else try {
|
|
33
|
-
l = (await import("./dist-
|
|
33
|
+
l = (await import("./dist-CZH1oldV.js")).compileDefinitions;
|
|
34
34
|
} catch (e) {
|
|
35
35
|
console.error("❌ Could not resolve Kama Schema Engine:", e), process.exit(1);
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,33 +1,73 @@
|
|
|
1
1
|
---
|
|
2
2
|
// src/components/global/Footer.astro
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import BlockRenderer from "@/components/blocks/BlockRenderer.astro";
|
|
5
|
+
import { getChannelId } from "@/lib/cms";
|
|
6
|
+
|
|
7
|
+
// 🎯 Fetch data natively during the server request
|
|
8
|
+
const safeEnv = (Astro.locals as any).safeEnv || {};
|
|
9
|
+
const cmsWorker = safeEnv.CMS_WORKER;
|
|
10
|
+
const channelId = getChannelId() || "website";
|
|
11
|
+
|
|
12
|
+
const customFetch = (input: RequestInfo | URL, init?: RequestInit) => {
|
|
13
|
+
const reqInit = { ...init };
|
|
14
|
+
delete reqInit.cache;
|
|
15
|
+
|
|
16
|
+
let urlStr = input instanceof URL ? input.toString() : String(input);
|
|
17
|
+
if (urlStr.startsWith("/")) {
|
|
18
|
+
const baseUrl =
|
|
19
|
+
import.meta.env.PUBLIC_API_URL ||
|
|
20
|
+
safeEnv.PUBLIC_API_URL ||
|
|
21
|
+
"http://127.0.0.1:8787";
|
|
22
|
+
urlStr = `${baseUrl}${urlStr}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const req = new Request(urlStr, reqInit);
|
|
26
|
+
if (cmsWorker && typeof cmsWorker.fetch === "function") {
|
|
27
|
+
return cmsWorker.fetch(req);
|
|
28
|
+
}
|
|
29
|
+
return fetch(req);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// 🎯 Resolve the Home Page slug
|
|
33
|
+
const homeSlug = String(import.meta.env.PUBLIC_HOME_SLUG || "home").trim();
|
|
34
|
+
|
|
35
|
+
let footerBlocks: any[] = [];
|
|
36
|
+
let contentMap: Record<string, any[]> = {};
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const res = await customFetch(
|
|
40
|
+
`/api/v1/node/${homeSlug}?channelId=${channelId}`,
|
|
41
|
+
);
|
|
42
|
+
if (res.ok) {
|
|
43
|
+
const data = await res.json();
|
|
44
|
+
const allContent = data.content || {};
|
|
45
|
+
footerBlocks = allContent.footer || [];
|
|
46
|
+
contentMap = allContent;
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error("[Footer] Failed to fetch home page blocks:", e);
|
|
50
|
+
}
|
|
4
51
|
---
|
|
5
52
|
|
|
6
53
|
<footer class="site-footer">
|
|
7
|
-
<div class="footer-container"
|
|
8
|
-
|
|
54
|
+
<div class="footer-container">
|
|
55
|
+
{
|
|
56
|
+
footerBlocks && footerBlocks.length > 0 ? (
|
|
57
|
+
<BlockRenderer
|
|
58
|
+
blocks={footerBlocks}
|
|
59
|
+
contentMap={contentMap}
|
|
60
|
+
region="footer"
|
|
61
|
+
/>
|
|
62
|
+
) : (
|
|
63
|
+
<div class="footer-default">
|
|
64
|
+
<p>© {new Date().getFullYear()} all rights reserved.</p>
|
|
65
|
+
</div>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
9
68
|
</div>
|
|
10
69
|
</footer>
|
|
11
70
|
|
|
12
|
-
<script>
|
|
13
|
-
async function initFooter() {
|
|
14
|
-
const target = document.getElementById("footer-injection-target");
|
|
15
|
-
if (!target) return;
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const res = await fetch(`/partials/footer`);
|
|
19
|
-
if (res.ok) {
|
|
20
|
-
target.innerHTML = await res.text();
|
|
21
|
-
}
|
|
22
|
-
} catch (e) {
|
|
23
|
-
console.error("Failed to load footer partial", e);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Run immediately
|
|
28
|
-
initFooter();
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
71
|
<style>
|
|
32
72
|
.site-footer {
|
|
33
73
|
background: #ffffff;
|
|
@@ -41,8 +81,7 @@
|
|
|
41
81
|
padding: 24px 20px;
|
|
42
82
|
}
|
|
43
83
|
|
|
44
|
-
|
|
45
|
-
:global(.footer-default p) {
|
|
84
|
+
.footer-default p {
|
|
46
85
|
margin: 0;
|
|
47
86
|
font-size: 14px;
|
|
48
87
|
color: #64748b;
|
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
// src/components/global/NavigationMenu.astro
|
|
3
|
+
import type { TreeNode } from "@/lib/cms";
|
|
4
|
+
|
|
5
|
+
export interface Props {
|
|
6
|
+
tree?: TreeNode[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { tree = [] } = Astro.props;
|
|
10
|
+
|
|
11
|
+
// 🎯 Grab the current path directly from Astro's server request
|
|
12
|
+
const currentPath = Astro.url.pathname.replace(/\/$/, "") || "/";
|
|
13
|
+
const homeSlug = String(import.meta.env.PUBLIC_HOME_SLUG || "home").trim();
|
|
14
|
+
|
|
15
|
+
const homeNode = tree.find(
|
|
16
|
+
item =>
|
|
17
|
+
item.slug === homeSlug ||
|
|
18
|
+
item.slug === "" ||
|
|
19
|
+
item.path === "/" ||
|
|
20
|
+
item.path === "",
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const topLevelNavItems =
|
|
24
|
+
homeNode?.children && homeNode.children.length > 0
|
|
25
|
+
? homeNode.children
|
|
26
|
+
: tree.filter(
|
|
27
|
+
item =>
|
|
28
|
+
item.slug !== homeSlug &&
|
|
29
|
+
item.slug !== "" &&
|
|
30
|
+
item.path !== "/" &&
|
|
31
|
+
item.path !== "",
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const isPathActive = (itemPath?: string) => {
|
|
35
|
+
const normItem = (itemPath || "").replace(/\/$/, "") || "/";
|
|
36
|
+
if (normItem === "/") return currentPath === "/";
|
|
37
|
+
return currentPath === normItem || currentPath.startsWith(`${normItem}/`);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const isExactActive = (itemPath?: string) => {
|
|
41
|
+
return currentPath === ((itemPath || "").replace(/\/$/, "") || "/");
|
|
42
|
+
};
|
|
3
43
|
---
|
|
4
44
|
|
|
5
45
|
<!-- 2-LINE HAMBURGER TOGGLE BUTTON -->
|
|
@@ -16,30 +56,78 @@
|
|
|
16
56
|
|
|
17
57
|
<!-- NAVIGATION BLOCK & FULLSCREEN CONTAINER -->
|
|
18
58
|
<nav class="nav-block" id="nav-overlay">
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
59
|
+
<ul class="nav-list">
|
|
60
|
+
{
|
|
61
|
+
topLevelNavItems.map(item => {
|
|
62
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
63
|
+
const isParentActive = isPathActive(item.path);
|
|
22
64
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
if (hasChildren) {
|
|
66
|
+
return (
|
|
67
|
+
<li class="nav-item">
|
|
68
|
+
<details class="nav-details">
|
|
69
|
+
<summary
|
|
70
|
+
class:list={[
|
|
71
|
+
"nav-button",
|
|
72
|
+
"dropdown-summary",
|
|
73
|
+
{ active: isParentActive },
|
|
74
|
+
]}
|
|
75
|
+
>
|
|
76
|
+
<span>{item.title}</span>
|
|
77
|
+
<span class="indicator">▼</span>
|
|
78
|
+
</summary>
|
|
79
|
+
<div class="submenu-container">
|
|
80
|
+
<ul class="dropdown-panel">
|
|
81
|
+
<li>
|
|
82
|
+
<a
|
|
83
|
+
href={item.path}
|
|
84
|
+
class:list={[
|
|
85
|
+
"dropdown-item",
|
|
86
|
+
"overview-item",
|
|
87
|
+
{ active: isExactActive(item.path) },
|
|
88
|
+
]}
|
|
89
|
+
>
|
|
90
|
+
{item.title} Overview
|
|
91
|
+
</a>
|
|
92
|
+
</li>
|
|
93
|
+
{item.children?.map(child => (
|
|
94
|
+
<li>
|
|
95
|
+
<a
|
|
96
|
+
href={child.path}
|
|
97
|
+
class:list={[
|
|
98
|
+
"dropdown-item",
|
|
99
|
+
{ active: isExactActive(child.path) },
|
|
100
|
+
]}
|
|
101
|
+
>
|
|
102
|
+
{child.title}
|
|
103
|
+
</a>
|
|
104
|
+
</li>
|
|
105
|
+
))}
|
|
106
|
+
</ul>
|
|
107
|
+
</div>
|
|
108
|
+
</details>
|
|
109
|
+
</li>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
32
112
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
113
|
+
return (
|
|
114
|
+
<li class="nav-item">
|
|
115
|
+
<a
|
|
116
|
+
href={item.path}
|
|
117
|
+
class:list={["nav-button", { active: isExactActive(item.path) }]}
|
|
118
|
+
>
|
|
119
|
+
{item.title}
|
|
120
|
+
</a>
|
|
121
|
+
</li>
|
|
122
|
+
);
|
|
123
|
+
})
|
|
39
124
|
}
|
|
40
|
-
|
|
125
|
+
</ul>
|
|
126
|
+
</nav>
|
|
41
127
|
|
|
42
|
-
|
|
128
|
+
<script>
|
|
129
|
+
// 🎯 Clean, standard event listeners that run when the HTML is parsed
|
|
130
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
43
131
|
const toggleBtn = document.getElementById("menu-toggle");
|
|
44
132
|
const navOverlay = document.getElementById("nav-overlay");
|
|
45
133
|
|
|
@@ -84,10 +172,7 @@
|
|
|
84
172
|
}
|
|
85
173
|
});
|
|
86
174
|
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Run on page load
|
|
90
|
-
initNav();
|
|
175
|
+
});
|
|
91
176
|
</script>
|
|
92
177
|
|
|
93
178
|
<style>
|
|
@@ -147,8 +232,7 @@
|
|
|
147
232
|
pointer-events: auto;
|
|
148
233
|
}
|
|
149
234
|
|
|
150
|
-
|
|
151
|
-
:global(.nav-list) {
|
|
235
|
+
.nav-list {
|
|
152
236
|
display: flex;
|
|
153
237
|
flex-direction: column;
|
|
154
238
|
gap: 8px;
|
|
@@ -157,11 +241,11 @@
|
|
|
157
241
|
padding: 0;
|
|
158
242
|
width: 100%;
|
|
159
243
|
}
|
|
160
|
-
|
|
244
|
+
.nav-item {
|
|
161
245
|
position: relative;
|
|
162
246
|
width: 100%;
|
|
163
247
|
}
|
|
164
|
-
|
|
248
|
+
.nav-button {
|
|
165
249
|
display: flex;
|
|
166
250
|
align-items: center;
|
|
167
251
|
justify-content: space-between;
|
|
@@ -178,44 +262,44 @@
|
|
|
178
262
|
cursor: pointer;
|
|
179
263
|
box-sizing: border-box;
|
|
180
264
|
}
|
|
181
|
-
|
|
265
|
+
.nav-button:hover {
|
|
182
266
|
color: #0f172a;
|
|
183
267
|
background: #f8fafc;
|
|
184
268
|
}
|
|
185
|
-
|
|
269
|
+
.nav-button.active {
|
|
186
270
|
color: #0c4a6e;
|
|
187
271
|
font-weight: 600;
|
|
188
272
|
}
|
|
189
|
-
|
|
273
|
+
.dropdown-summary {
|
|
190
274
|
list-style: none;
|
|
191
275
|
user-select: none;
|
|
192
276
|
}
|
|
193
|
-
|
|
277
|
+
.dropdown-summary::-webkit-details-marker {
|
|
194
278
|
display: none;
|
|
195
279
|
}
|
|
196
|
-
|
|
280
|
+
.indicator {
|
|
197
281
|
font-size: 11px;
|
|
198
282
|
color: #64748b;
|
|
199
283
|
transition: transform 0.2s ease;
|
|
200
284
|
}
|
|
201
|
-
|
|
285
|
+
details[open] .indicator {
|
|
202
286
|
transform: rotate(180deg);
|
|
203
287
|
}
|
|
204
|
-
|
|
288
|
+
details.nav-details {
|
|
205
289
|
border-radius: 6px;
|
|
206
290
|
transition: background-color 0.2s ease;
|
|
207
291
|
}
|
|
208
|
-
|
|
292
|
+
details[open].nav-details {
|
|
209
293
|
background: #f8fafc;
|
|
210
294
|
padding-bottom: 8px;
|
|
211
295
|
}
|
|
212
|
-
|
|
296
|
+
.submenu-container {
|
|
213
297
|
position: relative;
|
|
214
298
|
margin-left: 24px;
|
|
215
299
|
padding-left: 16px;
|
|
216
300
|
border-left: 2px solid #cbd5e1;
|
|
217
301
|
}
|
|
218
|
-
|
|
302
|
+
.dropdown-panel {
|
|
219
303
|
list-style: none;
|
|
220
304
|
margin: 4px 0 0 0;
|
|
221
305
|
padding: 0;
|
|
@@ -223,7 +307,7 @@
|
|
|
223
307
|
flex-direction: column;
|
|
224
308
|
gap: 4px;
|
|
225
309
|
}
|
|
226
|
-
|
|
310
|
+
.dropdown-item {
|
|
227
311
|
display: block;
|
|
228
312
|
padding: 10px 12px;
|
|
229
313
|
font-size: 16px;
|
|
@@ -235,20 +319,20 @@
|
|
|
235
319
|
background 0.15s ease,
|
|
236
320
|
color 0.15s ease;
|
|
237
321
|
}
|
|
238
|
-
|
|
322
|
+
.overview-item {
|
|
239
323
|
font-weight: 500;
|
|
240
324
|
color: #334155;
|
|
241
325
|
}
|
|
242
|
-
|
|
326
|
+
.dropdown-item:hover {
|
|
243
327
|
background: #e2e8f0;
|
|
244
328
|
color: #0f172a;
|
|
245
329
|
}
|
|
246
|
-
|
|
330
|
+
.dropdown-item.active {
|
|
247
331
|
font-weight: 600;
|
|
248
332
|
color: #0c4a6e;
|
|
249
333
|
background: #e0f2fe;
|
|
250
334
|
}
|
|
251
|
-
|
|
335
|
+
body.menu-lock-scroll {
|
|
252
336
|
overflow: hidden !important;
|
|
253
337
|
}
|
|
254
338
|
|
|
@@ -268,15 +352,15 @@
|
|
|
268
352
|
overflow-y: visible;
|
|
269
353
|
display: block;
|
|
270
354
|
}
|
|
271
|
-
|
|
355
|
+
.nav-list {
|
|
272
356
|
flex-direction: row;
|
|
273
357
|
gap: 4px;
|
|
274
358
|
justify-content: flex-end;
|
|
275
359
|
}
|
|
276
|
-
|
|
360
|
+
.nav-item {
|
|
277
361
|
width: auto;
|
|
278
362
|
}
|
|
279
|
-
|
|
363
|
+
.nav-button {
|
|
280
364
|
display: inline-flex;
|
|
281
365
|
justify-content: flex-start;
|
|
282
366
|
gap: 6px;
|
|
@@ -286,16 +370,16 @@
|
|
|
286
370
|
border-radius: 4px;
|
|
287
371
|
margin-top: 4px;
|
|
288
372
|
}
|
|
289
|
-
|
|
373
|
+
details[open].nav-details {
|
|
290
374
|
background: transparent;
|
|
291
375
|
padding-bottom: 0;
|
|
292
376
|
}
|
|
293
|
-
|
|
377
|
+
.submenu-container {
|
|
294
378
|
margin-left: 0;
|
|
295
379
|
padding-left: 0;
|
|
296
380
|
border-left: none;
|
|
297
381
|
}
|
|
298
|
-
|
|
382
|
+
.dropdown-panel {
|
|
299
383
|
position: absolute;
|
|
300
384
|
top: 100%;
|
|
301
385
|
left: 0;
|
|
@@ -308,7 +392,7 @@
|
|
|
308
392
|
border-radius: 4px;
|
|
309
393
|
padding: 4px;
|
|
310
394
|
}
|
|
311
|
-
|
|
395
|
+
.dropdown-item {
|
|
312
396
|
font-size: 14px;
|
|
313
397
|
padding: 8px 16px;
|
|
314
398
|
border-radius: 4px;
|
|
@@ -57,9 +57,7 @@ const homeSlug = String(envHomeSlug || workerHomeSlug || "home").trim();
|
|
|
57
57
|
|
|
58
58
|
const envApiUrl = import.meta.env.PUBLIC_API_URL;
|
|
59
59
|
const workerApiUrl = safeEnv.PUBLIC_API_URL;
|
|
60
|
-
const baseApiUrl = String(
|
|
61
|
-
envApiUrl || workerApiUrl || "https://admin.kamaengine.com",
|
|
62
|
-
);
|
|
60
|
+
const baseApiUrl = String(envApiUrl || workerApiUrl || "http://localhost:8787");
|
|
63
61
|
|
|
64
62
|
const cleanApiUrl = baseApiUrl.endsWith("/")
|
|
65
63
|
? baseApiUrl.slice(0, -1)
|
|
@@ -175,7 +173,6 @@ const isSkeleton = node?.nodeType === "page-skeleton";
|
|
|
175
173
|
isHomePage={isHomePage}
|
|
176
174
|
>
|
|
177
175
|
<BlockRenderer blocks={mainBlocks} contentMap={content} region="main" />
|
|
178
|
-
<KamaLivePreviewListener />
|
|
179
176
|
</SkeletonLayout>
|
|
180
177
|
) : (
|
|
181
178
|
<StandardLayout
|
|
@@ -235,8 +232,6 @@ const isSkeleton = node?.nodeType === "page-skeleton";
|
|
|
235
232
|
</aside>
|
|
236
233
|
)}
|
|
237
234
|
</div>
|
|
238
|
-
|
|
239
|
-
<KamaLivePreviewListener />
|
|
240
235
|
</StandardLayout>
|
|
241
236
|
)
|
|
242
237
|
}
|