@xosen/site-sdk 0.0.13 → 0.0.14
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.
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared reactive store for page data loaded via usePageData.
|
|
3
|
+
* Allows useDynamicLayout to reactively read layout from fetched pages.
|
|
4
|
+
*/
|
|
5
|
+
export declare const pageDataStore: Record<string, any>;
|
|
6
|
+
/**
|
|
7
|
+
* Initialize store with preloaded data from __SITE_DATA__.
|
|
8
|
+
*/
|
|
9
|
+
export declare function initPageDataStore(): void;
|
package/dist/index.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { ref as w, onMounted as
|
|
1
|
+
import { ref as w, onMounted as T, watch as _, computed as u, onUnmounted as N, reactive as L, provide as P } from "vue";
|
|
2
2
|
import { useI18n as S } from "vue-i18n";
|
|
3
|
-
import { useRoute as
|
|
4
|
-
function
|
|
3
|
+
import { useRoute as I } from "vue-router";
|
|
4
|
+
function Z(o, a) {
|
|
5
5
|
const t = w(null), { locale: e } = S(), n = window.__SITE_DATA__, s = n?.locale;
|
|
6
6
|
function r() {
|
|
7
7
|
return n && n[o] && e.value === s ? (t.value = n[o], !0) : !1;
|
|
8
8
|
}
|
|
9
9
|
async function i() {
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const c = await fetch(`/api/content/${a}:${e.value}`);
|
|
12
|
+
c.ok && (t.value = await c.json());
|
|
13
13
|
} catch {
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return T(() => {
|
|
17
17
|
r() || i();
|
|
18
|
-
}),
|
|
18
|
+
}), _(e, () => {
|
|
19
19
|
i();
|
|
20
20
|
}), t;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
const o = window.__SITE_DATA__, a =
|
|
24
|
-
function
|
|
25
|
-
const
|
|
26
|
-
return typeof
|
|
22
|
+
function q() {
|
|
23
|
+
const o = window.__SITE_DATA__, a = u(() => o?.config || null), t = u(() => o?.components || {}), e = u(() => a.value?.navigation || []), n = u(() => a.value?.locales || []), s = u(() => a.value?.defaultLocale || "en"), r = u(() => a.value?.branding || {}), i = u(() => a.value?.footer || {}), c = u(() => a.value?.features || {});
|
|
24
|
+
function p(m) {
|
|
25
|
+
const g = c.value[m];
|
|
26
|
+
return typeof g == "boolean" ? g : typeof g == "object";
|
|
27
27
|
}
|
|
28
28
|
return {
|
|
29
29
|
config: a,
|
|
@@ -33,19 +33,19 @@ function B() {
|
|
|
33
33
|
defaultLocale: s,
|
|
34
34
|
branding: r,
|
|
35
35
|
footer: i,
|
|
36
|
-
features:
|
|
37
|
-
hasFeature:
|
|
36
|
+
features: c,
|
|
37
|
+
hasFeature: p
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function H(o) {
|
|
41
41
|
function a(t) {
|
|
42
42
|
const e = document.documentElement;
|
|
43
43
|
if (t.colors)
|
|
44
44
|
for (const [n, s] of Object.entries(t.colors))
|
|
45
|
-
s && e.style.setProperty(`--x-color-${
|
|
45
|
+
s && e.style.setProperty(`--x-color-${D(n)}`, s);
|
|
46
46
|
t.typography?.fontFamily && e.style.setProperty("--x-font-family", t.typography.fontFamily), t.typography?.headingFont && e.style.setProperty("--x-font-heading", t.typography.headingFont), t.typography?.baseFontSize && e.style.setProperty("--x-font-size", t.typography.baseFontSize), t.shape?.borderRadius && e.style.setProperty("--x-border-radius", t.shape.borderRadius), t.shape?.maxWidth && e.style.setProperty("--x-max-width", t.shape.maxWidth);
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
T(() => {
|
|
49
49
|
if (o) {
|
|
50
50
|
a(o);
|
|
51
51
|
return;
|
|
@@ -58,10 +58,10 @@ function Y(o) {
|
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function D(o) {
|
|
62
62
|
return o.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function Q() {
|
|
65
65
|
const a = window.__SITE_DATA__?.apiBase || "";
|
|
66
66
|
async function t(s) {
|
|
67
67
|
const r = await fetch(`${a}${s}`);
|
|
@@ -81,89 +81,99 @@ function X() {
|
|
|
81
81
|
getProducts: n
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
function
|
|
84
|
+
function A() {
|
|
85
85
|
try {
|
|
86
86
|
return window.self !== window.top;
|
|
87
87
|
} catch {
|
|
88
88
|
return !0;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
function
|
|
92
|
-
|
|
91
|
+
function V(o) {
|
|
92
|
+
A() && o.beforeEach((a, t) => !t.name);
|
|
93
93
|
}
|
|
94
|
-
function
|
|
95
|
-
const o = w(null), a = w(
|
|
94
|
+
function C() {
|
|
95
|
+
const o = w(null), a = w(A());
|
|
96
96
|
function t(e) {
|
|
97
97
|
const n = e.data;
|
|
98
98
|
n?.type === "xosen-preview-update" && n.page && (o.value = n.page, a.value = !0);
|
|
99
99
|
}
|
|
100
|
-
return
|
|
100
|
+
return T(() => {
|
|
101
101
|
window.addEventListener("message", t);
|
|
102
|
-
}),
|
|
102
|
+
}), N(() => {
|
|
103
103
|
window.removeEventListener("message", t);
|
|
104
104
|
}), {
|
|
105
105
|
previewPage: o,
|
|
106
106
|
isPreviewMode: a
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
-
const
|
|
110
|
-
function
|
|
111
|
-
const
|
|
109
|
+
const R = /* @__PURE__ */ Symbol("pageContext"), $ = L({});
|
|
110
|
+
function j() {
|
|
111
|
+
const o = window.__SITE_DATA__;
|
|
112
|
+
if (o)
|
|
113
|
+
for (const a of Object.keys(o))
|
|
114
|
+
a.startsWith("page:") && ($[a] = o[a]);
|
|
115
|
+
}
|
|
116
|
+
j();
|
|
117
|
+
function ee(o) {
|
|
118
|
+
const { locale: a } = S(), { previewPage: t, isPreviewMode: e } = C(), n = window.__SITE_DATA__, s = w(null), r = w(!0), i = w(!1), c = u(() => typeof o == "string" ? o : o.value), p = u(() => `page:${c.value}`), m = u(() => {
|
|
112
119
|
const l = e.value ? t.value : s.value;
|
|
113
120
|
if (!l) return {};
|
|
114
|
-
const { blocks:
|
|
115
|
-
return
|
|
121
|
+
const { blocks: f, meta: d, slug: W, locale: J, ...E } = l;
|
|
122
|
+
return E;
|
|
116
123
|
});
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
P(R, m);
|
|
125
|
+
const g = u(() => e.value && t.value?.slug === c.value ? t.value.blocks || [] : s.value?.blocks || []);
|
|
126
|
+
function b(l) {
|
|
127
|
+
s.value = l, l && ($[p.value] = l);
|
|
128
|
+
}
|
|
129
|
+
function y() {
|
|
130
|
+
const l = n?.[p.value];
|
|
131
|
+
return l && a.value === n?.locale ? (b(l), i.value = !1, v(), !0) : !1;
|
|
122
132
|
}
|
|
123
|
-
async function
|
|
133
|
+
async function h() {
|
|
124
134
|
r.value = !0, i.value = !1;
|
|
125
135
|
try {
|
|
126
|
-
const l = await fetch(`/api/content/${
|
|
127
|
-
l.ok ? (
|
|
136
|
+
const l = await fetch(`/api/content/${p.value}:${a.value}`);
|
|
137
|
+
l.ok ? (b(await l.json()), v()) : (b(null), i.value = !0);
|
|
128
138
|
} catch {
|
|
129
|
-
|
|
139
|
+
b(null), i.value = !0;
|
|
130
140
|
} finally {
|
|
131
141
|
r.value = !1;
|
|
132
142
|
}
|
|
133
143
|
}
|
|
134
|
-
function
|
|
144
|
+
function v() {
|
|
135
145
|
if (!s.value) return;
|
|
136
146
|
if (s.value.title) {
|
|
137
|
-
const
|
|
138
|
-
document.title = `${s.value.title}${
|
|
147
|
+
const f = n?.config?.branding, d = f?.siteName ? ` — ${f.siteName}` : "";
|
|
148
|
+
document.title = `${s.value.title}${d}`;
|
|
139
149
|
}
|
|
140
150
|
const l = s.value.meta?.description;
|
|
141
151
|
if (l) {
|
|
142
|
-
const
|
|
143
|
-
|
|
152
|
+
const f = document.querySelector('meta[name="description"]');
|
|
153
|
+
f && f.setAttribute("content", l);
|
|
144
154
|
}
|
|
145
155
|
}
|
|
146
|
-
return
|
|
147
|
-
l?.slug ===
|
|
156
|
+
return _(t, (l) => {
|
|
157
|
+
l?.slug === c.value && (r.value = !1, i.value = !1, (l.title || l.blocks) && (s.value = {
|
|
148
158
|
...s.value || {},
|
|
149
159
|
...l.title ? { title: l.title } : {},
|
|
150
160
|
...l.blocks ? { blocks: l.blocks } : {}
|
|
151
|
-
},
|
|
152
|
-
}),
|
|
153
|
-
|
|
154
|
-
}),
|
|
155
|
-
|
|
161
|
+
}, v()));
|
|
162
|
+
}), T(() => {
|
|
163
|
+
y() ? r.value = !1 : h();
|
|
164
|
+
}), _(a, () => h()), _(c, () => {
|
|
165
|
+
y() ? r.value = !1 : h();
|
|
156
166
|
}), {
|
|
157
167
|
page: s,
|
|
158
|
-
blocks:
|
|
159
|
-
pageContext:
|
|
168
|
+
blocks: g,
|
|
169
|
+
pageContext: m,
|
|
160
170
|
loading: r,
|
|
161
171
|
notFound: i,
|
|
162
172
|
isPreviewMode: e,
|
|
163
|
-
reload:
|
|
173
|
+
reload: h
|
|
164
174
|
};
|
|
165
175
|
}
|
|
166
|
-
function
|
|
176
|
+
function te() {
|
|
167
177
|
const { locale: o } = S(), a = window.__SITE_DATA__, t = a?.locale, e = w({ ...a?.components || {} });
|
|
168
178
|
async function n(r) {
|
|
169
179
|
if (r === t) {
|
|
@@ -176,11 +186,11 @@ function H() {
|
|
|
176
186
|
} catch {
|
|
177
187
|
}
|
|
178
188
|
}
|
|
179
|
-
|
|
189
|
+
_(o, (r) => n(r)), T(() => {
|
|
180
190
|
o.value !== t && n(o.value);
|
|
181
191
|
});
|
|
182
192
|
function s(r) {
|
|
183
|
-
return
|
|
193
|
+
return u(() => e.value[r] || null);
|
|
184
194
|
}
|
|
185
195
|
return {
|
|
186
196
|
/** All components (reactive, locale-aware) */
|
|
@@ -191,8 +201,8 @@ function H() {
|
|
|
191
201
|
reload: () => n(o.value)
|
|
192
202
|
};
|
|
193
203
|
}
|
|
194
|
-
function
|
|
195
|
-
const { locale: o } = S(), a = window.__SITE_DATA__, t =
|
|
204
|
+
function ae() {
|
|
205
|
+
const { locale: o } = S(), a = window.__SITE_DATA__, t = u(() => a?.config?.locales || []), e = u(() => a?.config?.defaultLocale || "en"), n = u(() => t.value.length > 1);
|
|
196
206
|
function s(i) {
|
|
197
207
|
o.value = i, localStorage.setItem("x-site-locale", i);
|
|
198
208
|
}
|
|
@@ -208,12 +218,12 @@ function Q() {
|
|
|
208
218
|
resolveText: r
|
|
209
219
|
};
|
|
210
220
|
}
|
|
211
|
-
const
|
|
221
|
+
const O = {
|
|
212
222
|
sm: 600,
|
|
213
223
|
md: 960,
|
|
214
224
|
lg: 1280,
|
|
215
225
|
xl: 1920
|
|
216
|
-
},
|
|
226
|
+
}, z = {
|
|
217
227
|
grid: {
|
|
218
228
|
default: {
|
|
219
229
|
areas: ["header", "main", "footer"],
|
|
@@ -225,7 +235,7 @@ const R = {
|
|
|
225
235
|
main: { type: "slot" },
|
|
226
236
|
footer: { component: "footer" }
|
|
227
237
|
}
|
|
228
|
-
},
|
|
238
|
+
}, F = {
|
|
229
239
|
grid: {
|
|
230
240
|
default: {
|
|
231
241
|
areas: ["main"]
|
|
@@ -235,7 +245,7 @@ const R = {
|
|
|
235
245
|
main: { type: "slot" }
|
|
236
246
|
}
|
|
237
247
|
};
|
|
238
|
-
function
|
|
248
|
+
function k(o, a) {
|
|
239
249
|
const t = [];
|
|
240
250
|
if (o.areas?.length) {
|
|
241
251
|
const e = o.areas.map((n) => `"${n}"`).join(" ");
|
|
@@ -243,47 +253,47 @@ function $(o, a) {
|
|
|
243
253
|
}
|
|
244
254
|
return o.columns && t.push(`grid-template-columns: ${o.columns}`), o.rows && t.push(`grid-template-rows: ${o.rows}`), o.gap && t.push(`gap: ${o.gap}`), t.length ? `${a} { ${t.join("; ")}; }` : "";
|
|
245
255
|
}
|
|
246
|
-
function
|
|
256
|
+
function G(o, a) {
|
|
247
257
|
const t = [`${a} { display: grid; min-height: 100vh; }`], e = o.grid;
|
|
248
258
|
if (!e) return t.join(`
|
|
249
259
|
`);
|
|
250
260
|
if (e.default) {
|
|
251
|
-
const n =
|
|
261
|
+
const n = k(e.default, a);
|
|
252
262
|
n && t.push(n);
|
|
253
263
|
}
|
|
254
264
|
for (const n of ["sm", "md", "lg", "xl"]) {
|
|
255
265
|
const s = e[n];
|
|
256
266
|
if (!s) continue;
|
|
257
|
-
const r =
|
|
258
|
-
r && t.push(`@media (min-width: ${
|
|
267
|
+
const r = k(s, a);
|
|
268
|
+
r && t.push(`@media (min-width: ${O[n]}px) { ${r} }`);
|
|
259
269
|
}
|
|
260
270
|
return t.join(`
|
|
261
271
|
`);
|
|
262
272
|
}
|
|
263
|
-
function
|
|
264
|
-
const o =
|
|
273
|
+
function oe() {
|
|
274
|
+
const o = I(), { previewPage: a, isPreviewMode: t } = C(), e = window.__SITE_DATA__, n = `dl-${Math.random().toString(36).slice(2, 8)}`, s = u(() => ["dynamic-layout", n]), r = u(() => {
|
|
265
275
|
if (o.path === "/_preview_")
|
|
266
276
|
return a.value?.layout || "landing";
|
|
267
277
|
if (t.value && a.value?.layout)
|
|
268
278
|
return a.value.layout;
|
|
269
|
-
const
|
|
270
|
-
return e?.[
|
|
271
|
-
}), i =
|
|
272
|
-
const
|
|
273
|
-
if (
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
279
|
+
const p = o.path === "/" ? "page:home" : `page:${o.params.slug || ""}`;
|
|
280
|
+
return ($[p] || e?.[p])?.layout || "default";
|
|
281
|
+
}), i = u(() => {
|
|
282
|
+
const p = e?.config?.layouts;
|
|
283
|
+
if (p) {
|
|
284
|
+
const m = p[r.value] || p.default;
|
|
285
|
+
if (m?.zones) return m;
|
|
276
286
|
}
|
|
277
|
-
return r.value === "landing" ?
|
|
278
|
-
}),
|
|
287
|
+
return r.value === "landing" ? F : z;
|
|
288
|
+
}), c = u(() => G(i.value, `.${n}`));
|
|
279
289
|
return {
|
|
280
290
|
layoutName: r,
|
|
281
291
|
layoutConfig: i,
|
|
282
|
-
layoutCSS:
|
|
292
|
+
layoutCSS: c,
|
|
283
293
|
layoutClass: s
|
|
284
294
|
};
|
|
285
295
|
}
|
|
286
|
-
const
|
|
296
|
+
const ne = {
|
|
287
297
|
type: "layout",
|
|
288
298
|
displayName: "Layout",
|
|
289
299
|
description: "CSS Grid layout with responsive breakpoints and component zones",
|
|
@@ -317,7 +327,7 @@ const ee = {
|
|
|
317
327
|
{ key: "class", type: "text", label: "CSS Class" },
|
|
318
328
|
{ key: "container", type: "switch", label: "Wrap in Container" }
|
|
319
329
|
]
|
|
320
|
-
},
|
|
330
|
+
}, se = {
|
|
321
331
|
default: {
|
|
322
332
|
displayName: "Full Width",
|
|
323
333
|
config: {
|
|
@@ -385,8 +395,8 @@ const ee = {
|
|
|
385
395
|
}
|
|
386
396
|
}
|
|
387
397
|
}
|
|
388
|
-
},
|
|
389
|
-
function
|
|
398
|
+
}, M = /\.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|webp|avif|map|json|txt|xml|webmanifest)$/;
|
|
399
|
+
function U(o, a) {
|
|
390
400
|
const e = new URL(o.url).searchParams.get("lang");
|
|
391
401
|
if (e && a.supportedLocales?.includes(e)) return e;
|
|
392
402
|
if (a.supportedLocales?.length) {
|
|
@@ -396,7 +406,7 @@ function F(o, a) {
|
|
|
396
406
|
}
|
|
397
407
|
return a.defaultLocale;
|
|
398
408
|
}
|
|
399
|
-
function
|
|
409
|
+
function K(o, a, t) {
|
|
400
410
|
if (!o.pathname.startsWith("/api/content/")) return null;
|
|
401
411
|
const e = decodeURIComponent(o.pathname.replace("/api/content/", ""));
|
|
402
412
|
return e ? (async () => {
|
|
@@ -414,7 +424,7 @@ function G(o, a, t) {
|
|
|
414
424
|
}) : Response.json({ error: "Not found" }, { status: 404 });
|
|
415
425
|
})() : Promise.resolve(Response.json({ error: "Key is required" }, { status: 400 }));
|
|
416
426
|
}
|
|
417
|
-
function
|
|
427
|
+
function x(o, a, t) {
|
|
418
428
|
let e = o;
|
|
419
429
|
if (a.title) {
|
|
420
430
|
const n = t ? ` — ${t}` : "";
|
|
@@ -422,46 +432,46 @@ function k(o, a, t) {
|
|
|
422
432
|
}
|
|
423
433
|
return a.meta?.description && (e = e.replace(/(<meta\s+name="description"\s+content=")[^"]*(")/, `$1${a.meta.description}$2`)), a.meta?.ogTitle && (e = e.replace(/(<meta\s+property="og:title"\s+content=")[^"]*(")/, `$1${a.meta.ogTitle}$2`)), a.html && (e = e.replace('<div id="app"></div>', `<div id="app">${a.html}</div>`)), e;
|
|
424
434
|
}
|
|
425
|
-
function
|
|
435
|
+
function re(o) {
|
|
426
436
|
return {
|
|
427
437
|
async fetch(a, t) {
|
|
428
|
-
const e = new URL(a.url), n =
|
|
438
|
+
const e = new URL(a.url), n = K(e, t, o.defaultLocale);
|
|
429
439
|
if (n) return n;
|
|
430
|
-
if (
|
|
440
|
+
if (M.test(e.pathname))
|
|
431
441
|
return t.ASSETS.fetch(a);
|
|
432
|
-
const s =
|
|
433
|
-
let
|
|
434
|
-
const
|
|
442
|
+
const s = U(a, o), r = new URL("/index.html", a.url);
|
|
443
|
+
let c = await (await t.ASSETS.fetch(new Request(r))).text();
|
|
444
|
+
const p = o.defaultLocale, [m, g] = await Promise.all([
|
|
435
445
|
t.SITE_CONTENT.get("config"),
|
|
436
446
|
t.SITE_CONTENT.get(`content:${s}`)
|
|
437
|
-
]),
|
|
438
|
-
let
|
|
439
|
-
if (!
|
|
440
|
-
const
|
|
441
|
-
|
|
447
|
+
]), b = m ? JSON.parse(m) : {};
|
|
448
|
+
let y = g ? JSON.parse(g) : {};
|
|
449
|
+
if (!g && s !== p) {
|
|
450
|
+
const f = await t.SITE_CONTENT.get(`content:${p}`);
|
|
451
|
+
f && (y = JSON.parse(f));
|
|
442
452
|
}
|
|
443
453
|
const h = e.pathname.match(/^\/p\/(.+)$/);
|
|
444
454
|
if (h) {
|
|
445
|
-
const
|
|
446
|
-
if (!
|
|
447
|
-
let
|
|
448
|
-
!
|
|
455
|
+
const f = h[1];
|
|
456
|
+
if (!y[f]) {
|
|
457
|
+
let d = await t.SITE_CONTENT.get(`page:${f}:${s}`);
|
|
458
|
+
!d && s !== p && (d = await t.SITE_CONTENT.get(`page:${f}:${p}`)), d && (y[f] = JSON.parse(d));
|
|
449
459
|
}
|
|
450
460
|
}
|
|
451
|
-
const
|
|
461
|
+
const v = {
|
|
452
462
|
locale: s,
|
|
453
|
-
config:
|
|
463
|
+
config: b
|
|
454
464
|
};
|
|
455
|
-
for (const [
|
|
456
|
-
|
|
465
|
+
for (const [f, d] of Object.entries(y))
|
|
466
|
+
v[`page:${f}`] = d;
|
|
457
467
|
if (h) {
|
|
458
|
-
const
|
|
459
|
-
|
|
468
|
+
const f = h[1], d = v[`page:${f}`];
|
|
469
|
+
d && (c = x(c, d, o.siteName));
|
|
460
470
|
}
|
|
461
|
-
e.pathname === "/" &&
|
|
462
|
-
const
|
|
463
|
-
return
|
|
464
|
-
</head>`), new Response(
|
|
471
|
+
e.pathname === "/" && y.home && (c = x(c, y.home, o.siteName));
|
|
472
|
+
const l = `<script>window.__SITE_DATA__ = ${JSON.stringify(v)};<\/script>`;
|
|
473
|
+
return c = c.replace("</head>", `${l}
|
|
474
|
+
</head>`), new Response(c, {
|
|
465
475
|
headers: {
|
|
466
476
|
"Content-Type": "text/html;charset=utf-8",
|
|
467
477
|
"Cache-Control": "public, max-age=60"
|
|
@@ -471,20 +481,20 @@ function ae(o) {
|
|
|
471
481
|
};
|
|
472
482
|
}
|
|
473
483
|
export {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
484
|
+
R as PAGE_CONTEXT_KEY,
|
|
485
|
+
G as buildLayoutCSS,
|
|
486
|
+
re as createSiteWorker,
|
|
487
|
+
A as isInPreview,
|
|
488
|
+
se as layoutPresets,
|
|
489
|
+
ne as layoutSchema,
|
|
490
|
+
V as setupPreviewRouter,
|
|
491
|
+
oe as useDynamicLayout,
|
|
492
|
+
C as useLivePreview,
|
|
493
|
+
ae as useLocaleSwitcher,
|
|
494
|
+
ee as usePageData,
|
|
495
|
+
Q as useSiteApi,
|
|
496
|
+
te as useSiteComponents,
|
|
497
|
+
q as useSiteConfig,
|
|
498
|
+
Z as useSiteData,
|
|
499
|
+
H as useSkin
|
|
490
500
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { reactive } from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared reactive store for page data loaded via usePageData.
|
|
5
|
+
* Allows useDynamicLayout to reactively read layout from fetched pages.
|
|
6
|
+
*/
|
|
7
|
+
export const pageDataStore = reactive<Record<string, any>>({});
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initialize store with preloaded data from __SITE_DATA__.
|
|
11
|
+
*/
|
|
12
|
+
export function initPageDataStore() {
|
|
13
|
+
const siteData = (window as any).__SITE_DATA__;
|
|
14
|
+
if (!siteData) return;
|
|
15
|
+
|
|
16
|
+
for (const key of Object.keys(siteData)) {
|
|
17
|
+
if (key.startsWith('page:')) {
|
|
18
|
+
pageDataStore[key] = siteData[key];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Auto-init on import
|
|
24
|
+
initPageDataStore();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { computed
|
|
1
|
+
import { computed } from 'vue';
|
|
2
2
|
import { useRoute } from 'vue-router';
|
|
3
3
|
|
|
4
4
|
import type { SiteData } from '../types/config.js';
|
|
5
5
|
import type { GridBreakpoint, LayoutConfig } from '../types/layout.js';
|
|
6
6
|
import { useLivePreview } from './useLivePreview.js';
|
|
7
|
+
import { pageDataStore } from './pageDataStore.js';
|
|
7
8
|
|
|
8
9
|
const BREAKPOINTS: Record<string, number> = {
|
|
9
10
|
sm: 600,
|
|
@@ -102,7 +103,8 @@ export function useDynamicLayout() {
|
|
|
102
103
|
return previewPage.value.layout;
|
|
103
104
|
}
|
|
104
105
|
const pageKey = route.path === '/' ? 'page:home' : `page:${route.params.slug || ''}`;
|
|
105
|
-
|
|
106
|
+
// Read from reactive store (updated by usePageData on fetch)
|
|
107
|
+
const pageData = pageDataStore[pageKey] || siteData?.[pageKey];
|
|
106
108
|
return pageData?.layout || 'default';
|
|
107
109
|
});
|
|
108
110
|
|
|
@@ -5,6 +5,7 @@ import type { Block } from '../types/blocks.js';
|
|
|
5
5
|
import type { PageConfig, PageContext, SiteData } from '../types/config.js';
|
|
6
6
|
import { PAGE_CONTEXT_KEY } from '../types/config.js';
|
|
7
7
|
import { useLivePreview } from './useLivePreview.js';
|
|
8
|
+
import { pageDataStore } from './pageDataStore.js';
|
|
8
9
|
|
|
9
10
|
export interface UsePageDataReturn {
|
|
10
11
|
/** Resolved page data (from preload, API, or preview) */
|
|
@@ -46,7 +47,7 @@ export function usePageData(slug: Ref<string> | string): UsePageDataReturn {
|
|
|
46
47
|
const pageContext = computed<PageContext>(() => {
|
|
47
48
|
const p = isPreviewMode.value ? previewPage.value : page.value;
|
|
48
49
|
if (!p) return {};
|
|
49
|
-
const { blocks, meta, slug: _s, locale: _l, ...rest } = p as any;
|
|
50
|
+
const { blocks: _blocks, meta: _meta, slug: _s, locale: _l, ...rest } = p as any;
|
|
50
51
|
return rest;
|
|
51
52
|
});
|
|
52
53
|
|
|
@@ -61,10 +62,17 @@ export function usePageData(slug: Ref<string> | string): UsePageDataReturn {
|
|
|
61
62
|
return page.value?.blocks || [];
|
|
62
63
|
});
|
|
63
64
|
|
|
65
|
+
function setPage(data: PageConfig | null) {
|
|
66
|
+
page.value = data;
|
|
67
|
+
if (data) {
|
|
68
|
+
pageDataStore[pageKey.value] = data;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
function loadFromPreloaded(): boolean {
|
|
65
73
|
const preloaded = siteData?.[pageKey.value];
|
|
66
74
|
if (preloaded && locale.value === siteData?.locale) {
|
|
67
|
-
|
|
75
|
+
setPage(preloaded as PageConfig);
|
|
68
76
|
notFound.value = false;
|
|
69
77
|
applyMeta();
|
|
70
78
|
return true;
|
|
@@ -78,14 +86,14 @@ export function usePageData(slug: Ref<string> | string): UsePageDataReturn {
|
|
|
78
86
|
try {
|
|
79
87
|
const res = await fetch(`/api/content/${pageKey.value}:${locale.value}`);
|
|
80
88
|
if (res.ok) {
|
|
81
|
-
|
|
89
|
+
setPage(await res.json());
|
|
82
90
|
applyMeta();
|
|
83
91
|
} else {
|
|
84
|
-
|
|
92
|
+
setPage(null);
|
|
85
93
|
notFound.value = true;
|
|
86
94
|
}
|
|
87
95
|
} catch {
|
|
88
|
-
|
|
96
|
+
setPage(null);
|
|
89
97
|
notFound.value = true;
|
|
90
98
|
} finally {
|
|
91
99
|
loading.value = false;
|