@xosen/site-sdk 0.0.12 → 0.0.13
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/composables/useDynamicLayout.d.ts +1 -17
- package/dist/index.d.ts +2 -1
- package/dist/index.js +286 -182
- package/dist/types/blocks.d.ts +3 -0
- package/dist/types/layout.d.ts +48 -0
- package/package.json +1 -1
- package/src/composables/useDynamicLayout.ts +1 -20
- package/src/index.ts +2 -1
- package/src/types/blocks.ts +3 -0
- package/src/types/layout.ts +158 -0
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
areas?: string[];
|
|
3
|
-
columns?: string;
|
|
4
|
-
rows?: string;
|
|
5
|
-
gap?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface LayoutZone {
|
|
8
|
-
type?: 'slot';
|
|
9
|
-
component?: string;
|
|
10
|
-
class?: string;
|
|
11
|
-
container?: boolean;
|
|
12
|
-
containerStyle?: Record<string, string>;
|
|
13
|
-
}
|
|
14
|
-
export interface LayoutConfig {
|
|
15
|
-
grid?: Record<string, GridBreakpoint>;
|
|
16
|
-
zones: Record<string, LayoutZone>;
|
|
17
|
-
}
|
|
1
|
+
import type { LayoutConfig } from '../types/layout.js';
|
|
18
2
|
/**
|
|
19
3
|
* Generate responsive CSS for a layout config.
|
|
20
4
|
* Returns a CSS string with media queries for each breakpoint.
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export type { UsePageDataReturn } from './composables/usePageData.js';
|
|
|
8
8
|
export { useSiteComponents } from './composables/useSiteComponents.js';
|
|
9
9
|
export { useLocaleSwitcher } from './composables/useLocaleSwitcher.js';
|
|
10
10
|
export { useDynamicLayout, buildLayoutCSS } from './composables/useDynamicLayout.js';
|
|
11
|
-
export type { LayoutConfig, LayoutZone, GridBreakpoint } from './
|
|
11
|
+
export type { LayoutConfig, LayoutZone, GridBreakpoint, LayoutSchemaDefinition, LayoutField } from './types/layout.js';
|
|
12
|
+
export { layoutSchema, layoutPresets } from './types/layout.js';
|
|
12
13
|
export type { PreviewMessage } from './composables/useLivePreview.js';
|
|
13
14
|
export { createSiteWorker } from './worker/index.js';
|
|
14
15
|
export type { WorkerEnv, WorkerConfig, PageData } from './worker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { ref as w, onMounted as
|
|
2
|
-
import { useI18n as
|
|
3
|
-
import { useRoute as
|
|
4
|
-
function
|
|
5
|
-
const t = w(null), { locale: e } =
|
|
6
|
-
function
|
|
7
|
-
return
|
|
1
|
+
import { ref as w, onMounted as _, watch as b, computed as c, onUnmounted as E, provide as N } from "vue";
|
|
2
|
+
import { useI18n as S } from "vue-i18n";
|
|
3
|
+
import { useRoute as L } from "vue-router";
|
|
4
|
+
function J(o, a) {
|
|
5
|
+
const t = w(null), { locale: e } = S(), n = window.__SITE_DATA__, s = n?.locale;
|
|
6
|
+
function r() {
|
|
7
|
+
return n && n[o] && e.value === s ? (t.value = n[o], !0) : !1;
|
|
8
8
|
}
|
|
9
|
-
async function
|
|
9
|
+
async function i() {
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const u = await fetch(`/api/content/${a}:${e.value}`);
|
|
12
|
+
u.ok && (t.value = await u.json());
|
|
13
13
|
} catch {
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
}),
|
|
19
|
-
|
|
16
|
+
return _(() => {
|
|
17
|
+
r() || i();
|
|
18
|
+
}), b(e, () => {
|
|
19
|
+
i();
|
|
20
20
|
}), t;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
const o = window.__SITE_DATA__,
|
|
22
|
+
function B() {
|
|
23
|
+
const o = window.__SITE_DATA__, a = c(() => o?.config || null), t = c(() => o?.components || {}), e = c(() => a.value?.navigation || []), n = c(() => a.value?.locales || []), s = c(() => a.value?.defaultLocale || "en"), r = c(() => a.value?.branding || {}), i = c(() => a.value?.footer || {}), u = c(() => a.value?.features || {});
|
|
24
24
|
function f(d) {
|
|
25
|
-
const
|
|
26
|
-
return typeof
|
|
25
|
+
const y = u.value[d];
|
|
26
|
+
return typeof y == "boolean" ? y : typeof y == "object";
|
|
27
27
|
}
|
|
28
28
|
return {
|
|
29
|
-
config:
|
|
29
|
+
config: a,
|
|
30
30
|
components: t,
|
|
31
31
|
navigation: e,
|
|
32
|
-
locales:
|
|
32
|
+
locales: n,
|
|
33
33
|
defaultLocale: s,
|
|
34
|
-
branding:
|
|
35
|
-
footer:
|
|
36
|
-
features:
|
|
34
|
+
branding: r,
|
|
35
|
+
footer: i,
|
|
36
|
+
features: u,
|
|
37
37
|
hasFeature: f
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
function Y(o) {
|
|
41
|
-
function
|
|
41
|
+
function a(t) {
|
|
42
42
|
const e = document.documentElement;
|
|
43
43
|
if (t.colors)
|
|
44
|
-
for (const [
|
|
45
|
-
s && e.style.setProperty(`--x-color-${
|
|
44
|
+
for (const [n, s] of Object.entries(t.colors))
|
|
45
|
+
s && e.style.setProperty(`--x-color-${P(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
|
+
_(() => {
|
|
49
49
|
if (o) {
|
|
50
|
-
|
|
50
|
+
a(o);
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
const e = window.__SITE_DATA__?.skin;
|
|
54
|
-
e && (e.colors || e.typography || e.shape) &&
|
|
54
|
+
e && (e.colors || e.typography || e.shape) && a({
|
|
55
55
|
colors: e.colors || {},
|
|
56
56
|
typography: e.typography || {},
|
|
57
57
|
shape: e.shape || {}
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function P(o) {
|
|
62
62
|
return o.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
63
63
|
}
|
|
64
64
|
function X() {
|
|
65
|
-
const
|
|
65
|
+
const a = window.__SITE_DATA__?.apiBase || "";
|
|
66
66
|
async function t(s) {
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
throw new Error(`API error: ${
|
|
70
|
-
return
|
|
67
|
+
const r = await fetch(`${a}${s}`);
|
|
68
|
+
if (!r.ok)
|
|
69
|
+
throw new Error(`API error: ${r.status}`);
|
|
70
|
+
return r.json();
|
|
71
71
|
}
|
|
72
72
|
async function e() {
|
|
73
73
|
return t("/v1/billing/tariffs");
|
|
74
74
|
}
|
|
75
|
-
async function
|
|
75
|
+
async function n() {
|
|
76
76
|
return t("/v1/billing/services");
|
|
77
77
|
}
|
|
78
78
|
return {
|
|
79
79
|
get: t,
|
|
80
80
|
getTariffs: e,
|
|
81
|
-
getProducts:
|
|
81
|
+
getProducts: n
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
function
|
|
84
|
+
function x() {
|
|
85
85
|
try {
|
|
86
86
|
return window.self !== window.top;
|
|
87
87
|
} catch {
|
|
@@ -89,98 +89,98 @@ function b() {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
function Z(o) {
|
|
92
|
-
|
|
92
|
+
x() && o.beforeEach((a, t) => !t.name);
|
|
93
93
|
}
|
|
94
|
-
function
|
|
95
|
-
const o = w(null),
|
|
94
|
+
function A() {
|
|
95
|
+
const o = w(null), a = w(x());
|
|
96
96
|
function t(e) {
|
|
97
|
-
const
|
|
98
|
-
|
|
97
|
+
const n = e.data;
|
|
98
|
+
n?.type === "xosen-preview-update" && n.page && (o.value = n.page, a.value = !0);
|
|
99
99
|
}
|
|
100
|
-
return
|
|
100
|
+
return _(() => {
|
|
101
101
|
window.addEventListener("message", t);
|
|
102
|
-
}),
|
|
102
|
+
}), E(() => {
|
|
103
103
|
window.removeEventListener("message", t);
|
|
104
104
|
}), {
|
|
105
105
|
previewPage: o,
|
|
106
|
-
isPreviewMode:
|
|
106
|
+
isPreviewMode: a
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
-
const
|
|
110
|
-
function
|
|
111
|
-
const { locale:
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
114
|
-
const { blocks:
|
|
115
|
-
return
|
|
109
|
+
const I = /* @__PURE__ */ Symbol("pageContext");
|
|
110
|
+
function q(o) {
|
|
111
|
+
const { locale: a } = S(), { previewPage: t, isPreviewMode: e } = A(), n = window.__SITE_DATA__, s = w(null), r = w(!0), i = w(!1), u = c(() => typeof o == "string" ? o : o.value), f = c(() => `page:${u.value}`), d = c(() => {
|
|
112
|
+
const l = e.value ? t.value : s.value;
|
|
113
|
+
if (!l) return {};
|
|
114
|
+
const { blocks: v, meta: p, slug: g, locale: M, ...C } = l;
|
|
115
|
+
return C;
|
|
116
116
|
});
|
|
117
|
-
I
|
|
118
|
-
const
|
|
119
|
-
function
|
|
120
|
-
const
|
|
121
|
-
return
|
|
117
|
+
N(I, d);
|
|
118
|
+
const y = c(() => e.value && t.value?.slug === u.value ? t.value.blocks || [] : s.value?.blocks || []);
|
|
119
|
+
function T() {
|
|
120
|
+
const l = n?.[f.value];
|
|
121
|
+
return l && a.value === n?.locale ? (s.value = l, i.value = !1, h(), !0) : !1;
|
|
122
122
|
}
|
|
123
|
-
async function
|
|
124
|
-
|
|
123
|
+
async function m() {
|
|
124
|
+
r.value = !0, i.value = !1;
|
|
125
125
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
126
|
+
const l = await fetch(`/api/content/${f.value}:${a.value}`);
|
|
127
|
+
l.ok ? (s.value = await l.json(), h()) : (s.value = null, i.value = !0);
|
|
128
128
|
} catch {
|
|
129
|
-
s.value = null,
|
|
129
|
+
s.value = null, i.value = !0;
|
|
130
130
|
} finally {
|
|
131
|
-
|
|
131
|
+
r.value = !1;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
function h() {
|
|
135
135
|
if (!s.value) return;
|
|
136
136
|
if (s.value.title) {
|
|
137
|
-
const
|
|
137
|
+
const v = n?.config?.branding, p = v?.siteName ? ` — ${v.siteName}` : "";
|
|
138
138
|
document.title = `${s.value.title}${p}`;
|
|
139
139
|
}
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
const
|
|
143
|
-
|
|
140
|
+
const l = s.value.meta?.description;
|
|
141
|
+
if (l) {
|
|
142
|
+
const v = document.querySelector('meta[name="description"]');
|
|
143
|
+
v && v.setAttribute("content", l);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
-
return
|
|
147
|
-
|
|
146
|
+
return b(t, (l) => {
|
|
147
|
+
l?.slug === u.value && (r.value = !1, i.value = !1, (l.title || l.blocks) && (s.value = {
|
|
148
148
|
...s.value || {},
|
|
149
|
-
...
|
|
150
|
-
...
|
|
149
|
+
...l.title ? { title: l.title } : {},
|
|
150
|
+
...l.blocks ? { blocks: l.blocks } : {}
|
|
151
151
|
}, h()));
|
|
152
|
-
}),
|
|
153
|
-
|
|
154
|
-
}),
|
|
155
|
-
|
|
152
|
+
}), _(() => {
|
|
153
|
+
T() ? r.value = !1 : m();
|
|
154
|
+
}), b(a, () => m()), b(u, () => {
|
|
155
|
+
T() ? r.value = !1 : m();
|
|
156
156
|
}), {
|
|
157
157
|
page: s,
|
|
158
|
-
blocks:
|
|
158
|
+
blocks: y,
|
|
159
159
|
pageContext: d,
|
|
160
|
-
loading:
|
|
161
|
-
notFound:
|
|
160
|
+
loading: r,
|
|
161
|
+
notFound: i,
|
|
162
162
|
isPreviewMode: e,
|
|
163
|
-
reload:
|
|
163
|
+
reload: m
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
function
|
|
167
|
-
const { locale: o } =
|
|
168
|
-
async function
|
|
169
|
-
if (
|
|
170
|
-
e.value = { ...
|
|
166
|
+
function H() {
|
|
167
|
+
const { locale: o } = S(), a = window.__SITE_DATA__, t = a?.locale, e = w({ ...a?.components || {} });
|
|
168
|
+
async function n(r) {
|
|
169
|
+
if (r === t) {
|
|
170
|
+
e.value = { ...a?.components || {} };
|
|
171
171
|
return;
|
|
172
172
|
}
|
|
173
173
|
try {
|
|
174
|
-
const
|
|
175
|
-
|
|
174
|
+
const i = await fetch(`/api/content/components:${r}`);
|
|
175
|
+
i.ok && (e.value = await i.json());
|
|
176
176
|
} catch {
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
|
|
180
|
-
o.value !== t &&
|
|
179
|
+
b(o, (r) => n(r)), _(() => {
|
|
180
|
+
o.value !== t && n(o.value);
|
|
181
181
|
});
|
|
182
|
-
function s(
|
|
183
|
-
return
|
|
182
|
+
function s(r) {
|
|
183
|
+
return c(() => e.value[r] || null);
|
|
184
184
|
}
|
|
185
185
|
return {
|
|
186
186
|
/** All components (reactive, locale-aware) */
|
|
@@ -188,32 +188,32 @@ function Q() {
|
|
|
188
188
|
/** Get a single component by key */
|
|
189
189
|
getComponent: s,
|
|
190
190
|
/** Force refetch for current locale */
|
|
191
|
-
reload: () =>
|
|
191
|
+
reload: () => n(o.value)
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
|
-
function
|
|
195
|
-
const { locale: o } =
|
|
196
|
-
function s(
|
|
197
|
-
o.value =
|
|
194
|
+
function Q() {
|
|
195
|
+
const { locale: o } = S(), a = window.__SITE_DATA__, t = c(() => a?.config?.locales || []), e = c(() => a?.config?.defaultLocale || "en"), n = c(() => t.value.length > 1);
|
|
196
|
+
function s(i) {
|
|
197
|
+
o.value = i, localStorage.setItem("x-site-locale", i);
|
|
198
198
|
}
|
|
199
|
-
function i
|
|
200
|
-
return typeof
|
|
199
|
+
function r(i) {
|
|
200
|
+
return typeof i == "string" ? i : i[o.value] || i[e.value] || Object.values(i)[0] || "";
|
|
201
201
|
}
|
|
202
202
|
return {
|
|
203
203
|
locale: o,
|
|
204
204
|
locales: t,
|
|
205
205
|
defaultLocale: e,
|
|
206
|
-
hasMultipleLocales:
|
|
206
|
+
hasMultipleLocales: n,
|
|
207
207
|
switchLocale: s,
|
|
208
|
-
resolveText:
|
|
208
|
+
resolveText: r
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
|
-
const
|
|
211
|
+
const R = {
|
|
212
212
|
sm: 600,
|
|
213
213
|
md: 960,
|
|
214
214
|
lg: 1280,
|
|
215
215
|
xl: 1920
|
|
216
|
-
},
|
|
216
|
+
}, D = {
|
|
217
217
|
grid: {
|
|
218
218
|
default: {
|
|
219
219
|
areas: ["header", "main", "footer"],
|
|
@@ -225,7 +225,7 @@ const j = {
|
|
|
225
225
|
main: { type: "slot" },
|
|
226
226
|
footer: { component: "footer" }
|
|
227
227
|
}
|
|
228
|
-
},
|
|
228
|
+
}, j = {
|
|
229
229
|
grid: {
|
|
230
230
|
default: {
|
|
231
231
|
areas: ["main"]
|
|
@@ -235,75 +235,177 @@ const j = {
|
|
|
235
235
|
main: { type: "slot" }
|
|
236
236
|
}
|
|
237
237
|
};
|
|
238
|
-
function
|
|
238
|
+
function $(o, a) {
|
|
239
239
|
const t = [];
|
|
240
240
|
if (o.areas?.length) {
|
|
241
|
-
const e = o.areas.map((
|
|
241
|
+
const e = o.areas.map((n) => `"${n}"`).join(" ");
|
|
242
242
|
t.push(`grid-template-areas: ${e}`);
|
|
243
243
|
}
|
|
244
|
-
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 ? `${
|
|
244
|
+
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
245
|
}
|
|
246
|
-
function
|
|
247
|
-
const t = [`${
|
|
246
|
+
function O(o, a) {
|
|
247
|
+
const t = [`${a} { display: grid; min-height: 100vh; }`], e = o.grid;
|
|
248
248
|
if (!e) return t.join(`
|
|
249
249
|
`);
|
|
250
250
|
if (e.default) {
|
|
251
|
-
const
|
|
252
|
-
|
|
251
|
+
const n = $(e.default, a);
|
|
252
|
+
n && t.push(n);
|
|
253
253
|
}
|
|
254
|
-
for (const
|
|
255
|
-
const s = e[
|
|
254
|
+
for (const n of ["sm", "md", "lg", "xl"]) {
|
|
255
|
+
const s = e[n];
|
|
256
256
|
if (!s) continue;
|
|
257
|
-
const
|
|
258
|
-
|
|
257
|
+
const r = $(s, a);
|
|
258
|
+
r && t.push(`@media (min-width: ${R[n]}px) { ${r} }`);
|
|
259
259
|
}
|
|
260
260
|
return t.join(`
|
|
261
261
|
`);
|
|
262
262
|
}
|
|
263
|
-
function
|
|
264
|
-
const o =
|
|
263
|
+
function V() {
|
|
264
|
+
const o = L(), { previewPage: a, isPreviewMode: t } = A(), e = window.__SITE_DATA__, n = `dl-${Math.random().toString(36).slice(2, 8)}`, s = c(() => ["dynamic-layout", n]), r = c(() => {
|
|
265
265
|
if (o.path === "/_preview_")
|
|
266
|
-
return
|
|
267
|
-
if (t.value &&
|
|
268
|
-
return
|
|
266
|
+
return a.value?.layout || "landing";
|
|
267
|
+
if (t.value && a.value?.layout)
|
|
268
|
+
return a.value.layout;
|
|
269
269
|
const f = o.path === "/" ? "page:home" : `page:${o.params.slug || ""}`;
|
|
270
270
|
return e?.[f]?.layout || "default";
|
|
271
|
-
}),
|
|
271
|
+
}), i = c(() => {
|
|
272
272
|
const f = e?.config?.layouts;
|
|
273
273
|
if (f) {
|
|
274
|
-
const d = f[
|
|
274
|
+
const d = f[r.value] || f.default;
|
|
275
275
|
if (d?.zones) return d;
|
|
276
276
|
}
|
|
277
|
-
return
|
|
278
|
-
}),
|
|
277
|
+
return r.value === "landing" ? j : D;
|
|
278
|
+
}), u = c(() => O(i.value, `.${n}`));
|
|
279
279
|
return {
|
|
280
|
-
layoutName:
|
|
281
|
-
layoutConfig:
|
|
282
|
-
layoutCSS:
|
|
280
|
+
layoutName: r,
|
|
281
|
+
layoutConfig: i,
|
|
282
|
+
layoutCSS: u,
|
|
283
283
|
layoutClass: s
|
|
284
284
|
};
|
|
285
285
|
}
|
|
286
|
-
const
|
|
287
|
-
|
|
286
|
+
const ee = {
|
|
287
|
+
type: "layout",
|
|
288
|
+
displayName: "Layout",
|
|
289
|
+
description: "CSS Grid layout with responsive breakpoints and component zones",
|
|
290
|
+
fields: [
|
|
291
|
+
// Mobile (default)
|
|
292
|
+
{ key: "grid.default.areas", type: "grid-areas", label: "Grid Areas (mobile)", breakpoint: "default", required: !0 },
|
|
293
|
+
{ key: "grid.default.columns", type: "text", label: "Columns (mobile)", breakpoint: "default" },
|
|
294
|
+
{ key: "grid.default.rows", type: "text", label: "Rows (mobile)", breakpoint: "default" },
|
|
295
|
+
{ key: "grid.default.gap", type: "text", label: "Gap (mobile)", breakpoint: "default" },
|
|
296
|
+
// Tablet (sm — 600px)
|
|
297
|
+
{ key: "grid.sm.areas", type: "grid-areas", label: "Grid Areas (sm 600px+)", breakpoint: "sm" },
|
|
298
|
+
{ key: "grid.sm.columns", type: "text", label: "Columns (sm)", breakpoint: "sm" },
|
|
299
|
+
{ key: "grid.sm.rows", type: "text", label: "Rows (sm)", breakpoint: "sm" },
|
|
300
|
+
{ key: "grid.sm.gap", type: "text", label: "Gap (sm)", breakpoint: "sm" },
|
|
301
|
+
// Desktop (md — 960px)
|
|
302
|
+
{ key: "grid.md.areas", type: "grid-areas", label: "Grid Areas (md 960px+)", breakpoint: "md" },
|
|
303
|
+
{ key: "grid.md.columns", type: "text", label: "Columns (md)", breakpoint: "md" },
|
|
304
|
+
{ key: "grid.md.rows", type: "text", label: "Rows (md)", breakpoint: "md" },
|
|
305
|
+
{ key: "grid.md.gap", type: "text", label: "Gap (md)", breakpoint: "md" },
|
|
306
|
+
// Large desktop (lg — 1280px)
|
|
307
|
+
{ key: "grid.lg.areas", type: "grid-areas", label: "Grid Areas (lg 1280px+)", breakpoint: "lg" },
|
|
308
|
+
{ key: "grid.lg.columns", type: "text", label: "Columns (lg)", breakpoint: "lg" },
|
|
309
|
+
{ key: "grid.lg.rows", type: "text", label: "Rows (lg)", breakpoint: "lg" },
|
|
310
|
+
{ key: "grid.lg.gap", type: "text", label: "Gap (lg)", breakpoint: "lg" },
|
|
311
|
+
// Zones
|
|
312
|
+
{ key: "zones", type: "zone-list", label: "Zones", required: !0 }
|
|
313
|
+
],
|
|
314
|
+
zoneFields: [
|
|
315
|
+
{ key: "type", type: "select", label: "Type", options: ["slot", "component"] },
|
|
316
|
+
{ key: "component", type: "text", label: "Component Key" },
|
|
317
|
+
{ key: "class", type: "text", label: "CSS Class" },
|
|
318
|
+
{ key: "container", type: "switch", label: "Wrap in Container" }
|
|
319
|
+
]
|
|
320
|
+
}, te = {
|
|
321
|
+
default: {
|
|
322
|
+
displayName: "Full Width",
|
|
323
|
+
config: {
|
|
324
|
+
grid: {
|
|
325
|
+
default: { areas: ["header", "main", "footer"], rows: "auto 1fr auto" }
|
|
326
|
+
},
|
|
327
|
+
zones: {
|
|
328
|
+
header: { component: "nav-menu" },
|
|
329
|
+
main: { type: "slot" },
|
|
330
|
+
footer: { component: "footer" }
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
sidebar: {
|
|
335
|
+
displayName: "Sidebar",
|
|
336
|
+
config: {
|
|
337
|
+
grid: {
|
|
338
|
+
default: { areas: ["header", "main", "sidebar", "footer"], columns: "1fr", rows: "auto 1fr auto auto" },
|
|
339
|
+
md: { areas: ["header header", "sidebar main", "footer footer"], columns: "280px 1fr", rows: "auto 1fr auto" }
|
|
340
|
+
},
|
|
341
|
+
zones: {
|
|
342
|
+
header: { component: "nav-menu" },
|
|
343
|
+
sidebar: { component: "sidebar-menu" },
|
|
344
|
+
main: { type: "slot" },
|
|
345
|
+
footer: { component: "footer" }
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
article: {
|
|
350
|
+
displayName: "Article",
|
|
351
|
+
config: {
|
|
352
|
+
grid: {
|
|
353
|
+
default: { areas: ["header", "main", "footer"], rows: "auto 1fr auto" }
|
|
354
|
+
},
|
|
355
|
+
zones: {
|
|
356
|
+
header: { component: "nav-menu" },
|
|
357
|
+
main: { type: "slot", container: !0, containerStyle: { "max-width": "900px" } },
|
|
358
|
+
footer: { component: "footer" }
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
landing: {
|
|
363
|
+
displayName: "Landing (no nav)",
|
|
364
|
+
config: {
|
|
365
|
+
grid: {
|
|
366
|
+
default: { areas: ["main"] }
|
|
367
|
+
},
|
|
368
|
+
zones: {
|
|
369
|
+
main: { type: "slot" }
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
magazine: {
|
|
374
|
+
displayName: "Magazine",
|
|
375
|
+
config: {
|
|
376
|
+
grid: {
|
|
377
|
+
default: { areas: ["header", "main", "aside", "footer"], columns: "1fr", rows: "auto 1fr auto auto" },
|
|
378
|
+
md: { areas: ["header header header", "main main aside", "footer footer footer"], columns: "1fr 1fr 300px", rows: "auto 1fr auto", gap: "24px" }
|
|
379
|
+
},
|
|
380
|
+
zones: {
|
|
381
|
+
header: { component: "nav-menu" },
|
|
382
|
+
main: { type: "slot" },
|
|
383
|
+
aside: { component: "sidebar-menu" },
|
|
384
|
+
footer: { component: "footer" }
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}, z = /\.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|webp|avif|map|json|txt|xml|webmanifest)$/;
|
|
389
|
+
function F(o, a) {
|
|
288
390
|
const e = new URL(o.url).searchParams.get("lang");
|
|
289
|
-
if (e &&
|
|
290
|
-
if (
|
|
291
|
-
const
|
|
292
|
-
for (const s of
|
|
293
|
-
if (
|
|
391
|
+
if (e && a.supportedLocales?.includes(e)) return e;
|
|
392
|
+
if (a.supportedLocales?.length) {
|
|
393
|
+
const n = o.headers.get("Accept-Language") || "";
|
|
394
|
+
for (const s of a.supportedLocales)
|
|
395
|
+
if (n.includes(s)) return s;
|
|
294
396
|
}
|
|
295
|
-
return
|
|
397
|
+
return a.defaultLocale;
|
|
296
398
|
}
|
|
297
|
-
function
|
|
399
|
+
function G(o, a, t) {
|
|
298
400
|
if (!o.pathname.startsWith("/api/content/")) return null;
|
|
299
401
|
const e = decodeURIComponent(o.pathname.replace("/api/content/", ""));
|
|
300
402
|
return e ? (async () => {
|
|
301
|
-
let
|
|
302
|
-
if (!
|
|
403
|
+
let n = await a.SITE_CONTENT.get(e);
|
|
404
|
+
if (!n) {
|
|
303
405
|
const s = e.lastIndexOf(":");
|
|
304
|
-
s > 0 && e.slice(s + 1) !== t && (
|
|
406
|
+
s > 0 && e.slice(s + 1) !== t && (n = await a.SITE_CONTENT.get(e.slice(0, s + 1) + t));
|
|
305
407
|
}
|
|
306
|
-
return
|
|
408
|
+
return n ? new Response(n, {
|
|
307
409
|
headers: {
|
|
308
410
|
"Content-Type": "application/json",
|
|
309
411
|
"Cache-Control": "public, max-age=60",
|
|
@@ -312,54 +414,54 @@ function U(o, n, t) {
|
|
|
312
414
|
}) : Response.json({ error: "Not found" }, { status: 404 });
|
|
313
415
|
})() : Promise.resolve(Response.json({ error: "Key is required" }, { status: 400 }));
|
|
314
416
|
}
|
|
315
|
-
function
|
|
417
|
+
function k(o, a, t) {
|
|
316
418
|
let e = o;
|
|
317
|
-
if (
|
|
318
|
-
const
|
|
319
|
-
e = e.replace(/<title>[^<]*<\/title>/, `<title>${
|
|
419
|
+
if (a.title) {
|
|
420
|
+
const n = t ? ` — ${t}` : "";
|
|
421
|
+
e = e.replace(/<title>[^<]*<\/title>/, `<title>${a.title}${n}</title>`);
|
|
320
422
|
}
|
|
321
|
-
return
|
|
423
|
+
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;
|
|
322
424
|
}
|
|
323
|
-
function
|
|
425
|
+
function ae(o) {
|
|
324
426
|
return {
|
|
325
|
-
async fetch(
|
|
326
|
-
const e = new URL(
|
|
327
|
-
if (
|
|
328
|
-
if (
|
|
329
|
-
return t.ASSETS.fetch(
|
|
330
|
-
const s =
|
|
331
|
-
let
|
|
332
|
-
const f = o.defaultLocale, [d,
|
|
427
|
+
async fetch(a, t) {
|
|
428
|
+
const e = new URL(a.url), n = G(e, t, o.defaultLocale);
|
|
429
|
+
if (n) return n;
|
|
430
|
+
if (z.test(e.pathname))
|
|
431
|
+
return t.ASSETS.fetch(a);
|
|
432
|
+
const s = F(a, o), r = new URL("/index.html", a.url);
|
|
433
|
+
let u = await (await t.ASSETS.fetch(new Request(r))).text();
|
|
434
|
+
const f = o.defaultLocale, [d, y] = await Promise.all([
|
|
333
435
|
t.SITE_CONTENT.get("config"),
|
|
334
436
|
t.SITE_CONTENT.get(`content:${s}`)
|
|
335
|
-
]),
|
|
336
|
-
let
|
|
337
|
-
if (!
|
|
437
|
+
]), T = d ? JSON.parse(d) : {};
|
|
438
|
+
let m = y ? JSON.parse(y) : {};
|
|
439
|
+
if (!y && s !== f) {
|
|
338
440
|
const p = await t.SITE_CONTENT.get(`content:${f}`);
|
|
339
|
-
p && (
|
|
441
|
+
p && (m = JSON.parse(p));
|
|
340
442
|
}
|
|
341
443
|
const h = e.pathname.match(/^\/p\/(.+)$/);
|
|
342
444
|
if (h) {
|
|
343
445
|
const p = h[1];
|
|
344
|
-
if (!
|
|
345
|
-
let
|
|
346
|
-
!
|
|
446
|
+
if (!m[p]) {
|
|
447
|
+
let g = await t.SITE_CONTENT.get(`page:${p}:${s}`);
|
|
448
|
+
!g && s !== f && (g = await t.SITE_CONTENT.get(`page:${p}:${f}`)), g && (m[p] = JSON.parse(g));
|
|
347
449
|
}
|
|
348
450
|
}
|
|
349
|
-
const
|
|
451
|
+
const l = {
|
|
350
452
|
locale: s,
|
|
351
|
-
config:
|
|
453
|
+
config: T
|
|
352
454
|
};
|
|
353
|
-
for (const [p,
|
|
354
|
-
|
|
455
|
+
for (const [p, g] of Object.entries(m))
|
|
456
|
+
l[`page:${p}`] = g;
|
|
355
457
|
if (h) {
|
|
356
|
-
const p = h[1],
|
|
357
|
-
|
|
458
|
+
const p = h[1], g = l[`page:${p}`];
|
|
459
|
+
g && (u = k(u, g, o.siteName));
|
|
358
460
|
}
|
|
359
|
-
e.pathname === "/" &&
|
|
360
|
-
const
|
|
361
|
-
return
|
|
362
|
-
</head>`), new Response(
|
|
461
|
+
e.pathname === "/" && m.home && (u = k(u, m.home, o.siteName));
|
|
462
|
+
const v = `<script>window.__SITE_DATA__ = ${JSON.stringify(l)};<\/script>`;
|
|
463
|
+
return u = u.replace("</head>", `${v}
|
|
464
|
+
</head>`), new Response(u, {
|
|
363
465
|
headers: {
|
|
364
466
|
"Content-Type": "text/html;charset=utf-8",
|
|
365
467
|
"Cache-Control": "public, max-age=60"
|
|
@@ -369,18 +471,20 @@ function ee(o) {
|
|
|
369
471
|
};
|
|
370
472
|
}
|
|
371
473
|
export {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
474
|
+
I as PAGE_CONTEXT_KEY,
|
|
475
|
+
O as buildLayoutCSS,
|
|
476
|
+
ae as createSiteWorker,
|
|
477
|
+
x as isInPreview,
|
|
478
|
+
te as layoutPresets,
|
|
479
|
+
ee as layoutSchema,
|
|
376
480
|
Z as setupPreviewRouter,
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
481
|
+
V as useDynamicLayout,
|
|
482
|
+
A as useLivePreview,
|
|
483
|
+
Q as useLocaleSwitcher,
|
|
484
|
+
q as usePageData,
|
|
381
485
|
X as useSiteApi,
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
486
|
+
H as useSiteComponents,
|
|
487
|
+
B as useSiteConfig,
|
|
488
|
+
J as useSiteData,
|
|
385
489
|
Y as useSkin
|
|
386
490
|
};
|
package/dist/types/blocks.d.ts
CHANGED
|
@@ -12,9 +12,12 @@ export interface Block<T = any> {
|
|
|
12
12
|
settings?: BlockSettings & Record<string, any>;
|
|
13
13
|
}
|
|
14
14
|
export interface HeroBlockData {
|
|
15
|
+
variant?: 'default' | 'minimal' | 'video';
|
|
15
16
|
title: string;
|
|
16
17
|
subtitle?: string;
|
|
18
|
+
badge?: string;
|
|
17
19
|
image?: string;
|
|
20
|
+
backgroundImage?: string;
|
|
18
21
|
overlay?: boolean;
|
|
19
22
|
buttons?: Array<{
|
|
20
23
|
text: string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout schema definition for the editor.
|
|
3
|
+
* Describes the editable structure of a layout config.
|
|
4
|
+
*/
|
|
5
|
+
export interface GridBreakpoint {
|
|
6
|
+
areas?: string[];
|
|
7
|
+
columns?: string;
|
|
8
|
+
rows?: string;
|
|
9
|
+
gap?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface LayoutZone {
|
|
12
|
+
type?: 'slot';
|
|
13
|
+
component?: string;
|
|
14
|
+
class?: string;
|
|
15
|
+
container?: boolean;
|
|
16
|
+
containerStyle?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export interface LayoutConfig {
|
|
19
|
+
grid?: Record<string, GridBreakpoint>;
|
|
20
|
+
zones: Record<string, LayoutZone>;
|
|
21
|
+
}
|
|
22
|
+
export interface LayoutField {
|
|
23
|
+
key: string;
|
|
24
|
+
type: 'text' | 'grid-areas' | 'select' | 'switch' | 'zone-list';
|
|
25
|
+
label: string;
|
|
26
|
+
breakpoint?: string;
|
|
27
|
+
options?: string[];
|
|
28
|
+
required?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface LayoutSchemaDefinition {
|
|
31
|
+
type: string;
|
|
32
|
+
displayName: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
fields: LayoutField[];
|
|
35
|
+
zoneFields: LayoutField[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Schema describing how to edit a layout in the editor.
|
|
39
|
+
* Used to render a form for creating/editing layout configs.
|
|
40
|
+
*/
|
|
41
|
+
export declare const layoutSchema: LayoutSchemaDefinition;
|
|
42
|
+
/**
|
|
43
|
+
* Built-in layout presets for quick layout creation.
|
|
44
|
+
*/
|
|
45
|
+
export declare const layoutPresets: Record<string, {
|
|
46
|
+
displayName: string;
|
|
47
|
+
config: LayoutConfig;
|
|
48
|
+
}>;
|
package/package.json
CHANGED
|
@@ -2,28 +2,9 @@ import { computed, type Ref } from 'vue';
|
|
|
2
2
|
import { useRoute } from 'vue-router';
|
|
3
3
|
|
|
4
4
|
import type { SiteData } from '../types/config.js';
|
|
5
|
+
import type { GridBreakpoint, LayoutConfig } from '../types/layout.js';
|
|
5
6
|
import { useLivePreview } from './useLivePreview.js';
|
|
6
7
|
|
|
7
|
-
export interface GridBreakpoint {
|
|
8
|
-
areas?: string[];
|
|
9
|
-
columns?: string;
|
|
10
|
-
rows?: string;
|
|
11
|
-
gap?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface LayoutZone {
|
|
15
|
-
type?: 'slot';
|
|
16
|
-
component?: string;
|
|
17
|
-
class?: string;
|
|
18
|
-
container?: boolean;
|
|
19
|
-
containerStyle?: Record<string, string>;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface LayoutConfig {
|
|
23
|
-
grid?: Record<string, GridBreakpoint>;
|
|
24
|
-
zones: Record<string, LayoutZone>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
8
|
const BREAKPOINTS: Record<string, number> = {
|
|
28
9
|
sm: 600,
|
|
29
10
|
md: 960,
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,8 @@ export type { UsePageDataReturn } from './composables/usePageData.js';
|
|
|
9
9
|
export { useSiteComponents } from './composables/useSiteComponents.js';
|
|
10
10
|
export { useLocaleSwitcher } from './composables/useLocaleSwitcher.js';
|
|
11
11
|
export { useDynamicLayout, buildLayoutCSS } from './composables/useDynamicLayout.js';
|
|
12
|
-
export type { LayoutConfig, LayoutZone, GridBreakpoint } from './
|
|
12
|
+
export type { LayoutConfig, LayoutZone, GridBreakpoint, LayoutSchemaDefinition, LayoutField } from './types/layout.js';
|
|
13
|
+
export { layoutSchema, layoutPresets } from './types/layout.js';
|
|
13
14
|
export type { PreviewMessage } from './composables/useLivePreview.js';
|
|
14
15
|
|
|
15
16
|
// Worker
|
package/src/types/blocks.ts
CHANGED
|
@@ -14,9 +14,12 @@ export interface Block<T = any> {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface HeroBlockData {
|
|
17
|
+
variant?: 'default' | 'minimal' | 'video';
|
|
17
18
|
title: string;
|
|
18
19
|
subtitle?: string;
|
|
20
|
+
badge?: string;
|
|
19
21
|
image?: string;
|
|
22
|
+
backgroundImage?: string;
|
|
20
23
|
overlay?: boolean;
|
|
21
24
|
buttons?: Array<{ text: string; url: string; variant?: 'primary' | 'outline' | 'white' }>;
|
|
22
25
|
stats?: Array<{ value: string; label: string }>;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout schema definition for the editor.
|
|
3
|
+
* Describes the editable structure of a layout config.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface GridBreakpoint {
|
|
7
|
+
areas?: string[];
|
|
8
|
+
columns?: string;
|
|
9
|
+
rows?: string;
|
|
10
|
+
gap?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LayoutZone {
|
|
14
|
+
type?: 'slot';
|
|
15
|
+
component?: string;
|
|
16
|
+
class?: string;
|
|
17
|
+
container?: boolean;
|
|
18
|
+
containerStyle?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface LayoutConfig {
|
|
22
|
+
grid?: Record<string, GridBreakpoint>;
|
|
23
|
+
zones: Record<string, LayoutZone>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface LayoutField {
|
|
27
|
+
key: string;
|
|
28
|
+
type: 'text' | 'grid-areas' | 'select' | 'switch' | 'zone-list';
|
|
29
|
+
label: string;
|
|
30
|
+
breakpoint?: string;
|
|
31
|
+
options?: string[];
|
|
32
|
+
required?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface LayoutSchemaDefinition {
|
|
36
|
+
type: string;
|
|
37
|
+
displayName: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
fields: LayoutField[];
|
|
40
|
+
zoneFields: LayoutField[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Schema describing how to edit a layout in the editor.
|
|
45
|
+
* Used to render a form for creating/editing layout configs.
|
|
46
|
+
*/
|
|
47
|
+
export const layoutSchema: LayoutSchemaDefinition = {
|
|
48
|
+
type: 'layout',
|
|
49
|
+
displayName: 'Layout',
|
|
50
|
+
description: 'CSS Grid layout with responsive breakpoints and component zones',
|
|
51
|
+
fields: [
|
|
52
|
+
// Mobile (default)
|
|
53
|
+
{ key: 'grid.default.areas', type: 'grid-areas', label: 'Grid Areas (mobile)', breakpoint: 'default', required: true },
|
|
54
|
+
{ key: 'grid.default.columns', type: 'text', label: 'Columns (mobile)', breakpoint: 'default' },
|
|
55
|
+
{ key: 'grid.default.rows', type: 'text', label: 'Rows (mobile)', breakpoint: 'default' },
|
|
56
|
+
{ key: 'grid.default.gap', type: 'text', label: 'Gap (mobile)', breakpoint: 'default' },
|
|
57
|
+
|
|
58
|
+
// Tablet (sm — 600px)
|
|
59
|
+
{ key: 'grid.sm.areas', type: 'grid-areas', label: 'Grid Areas (sm 600px+)', breakpoint: 'sm' },
|
|
60
|
+
{ key: 'grid.sm.columns', type: 'text', label: 'Columns (sm)', breakpoint: 'sm' },
|
|
61
|
+
{ key: 'grid.sm.rows', type: 'text', label: 'Rows (sm)', breakpoint: 'sm' },
|
|
62
|
+
{ key: 'grid.sm.gap', type: 'text', label: 'Gap (sm)', breakpoint: 'sm' },
|
|
63
|
+
|
|
64
|
+
// Desktop (md — 960px)
|
|
65
|
+
{ key: 'grid.md.areas', type: 'grid-areas', label: 'Grid Areas (md 960px+)', breakpoint: 'md' },
|
|
66
|
+
{ key: 'grid.md.columns', type: 'text', label: 'Columns (md)', breakpoint: 'md' },
|
|
67
|
+
{ key: 'grid.md.rows', type: 'text', label: 'Rows (md)', breakpoint: 'md' },
|
|
68
|
+
{ key: 'grid.md.gap', type: 'text', label: 'Gap (md)', breakpoint: 'md' },
|
|
69
|
+
|
|
70
|
+
// Large desktop (lg — 1280px)
|
|
71
|
+
{ key: 'grid.lg.areas', type: 'grid-areas', label: 'Grid Areas (lg 1280px+)', breakpoint: 'lg' },
|
|
72
|
+
{ key: 'grid.lg.columns', type: 'text', label: 'Columns (lg)', breakpoint: 'lg' },
|
|
73
|
+
{ key: 'grid.lg.rows', type: 'text', label: 'Rows (lg)', breakpoint: 'lg' },
|
|
74
|
+
{ key: 'grid.lg.gap', type: 'text', label: 'Gap (lg)', breakpoint: 'lg' },
|
|
75
|
+
|
|
76
|
+
// Zones
|
|
77
|
+
{ key: 'zones', type: 'zone-list', label: 'Zones', required: true },
|
|
78
|
+
],
|
|
79
|
+
zoneFields: [
|
|
80
|
+
{ key: 'type', type: 'select', label: 'Type', options: ['slot', 'component'] },
|
|
81
|
+
{ key: 'component', type: 'text', label: 'Component Key' },
|
|
82
|
+
{ key: 'class', type: 'text', label: 'CSS Class' },
|
|
83
|
+
{ key: 'container', type: 'switch', label: 'Wrap in Container' },
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Built-in layout presets for quick layout creation.
|
|
89
|
+
*/
|
|
90
|
+
export const layoutPresets: Record<string, { displayName: string; config: LayoutConfig }> = {
|
|
91
|
+
default: {
|
|
92
|
+
displayName: 'Full Width',
|
|
93
|
+
config: {
|
|
94
|
+
grid: {
|
|
95
|
+
default: { areas: ['header', 'main', 'footer'], rows: 'auto 1fr auto' },
|
|
96
|
+
},
|
|
97
|
+
zones: {
|
|
98
|
+
header: { component: 'nav-menu' },
|
|
99
|
+
main: { type: 'slot' },
|
|
100
|
+
footer: { component: 'footer' },
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
sidebar: {
|
|
105
|
+
displayName: 'Sidebar',
|
|
106
|
+
config: {
|
|
107
|
+
grid: {
|
|
108
|
+
default: { areas: ['header', 'main', 'sidebar', 'footer'], columns: '1fr', rows: 'auto 1fr auto auto' },
|
|
109
|
+
md: { areas: ['header header', 'sidebar main', 'footer footer'], columns: '280px 1fr', rows: 'auto 1fr auto' },
|
|
110
|
+
},
|
|
111
|
+
zones: {
|
|
112
|
+
header: { component: 'nav-menu' },
|
|
113
|
+
sidebar: { component: 'sidebar-menu' },
|
|
114
|
+
main: { type: 'slot' },
|
|
115
|
+
footer: { component: 'footer' },
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
article: {
|
|
120
|
+
displayName: 'Article',
|
|
121
|
+
config: {
|
|
122
|
+
grid: {
|
|
123
|
+
default: { areas: ['header', 'main', 'footer'], rows: 'auto 1fr auto' },
|
|
124
|
+
},
|
|
125
|
+
zones: {
|
|
126
|
+
header: { component: 'nav-menu' },
|
|
127
|
+
main: { type: 'slot', container: true, containerStyle: { 'max-width': '900px' } },
|
|
128
|
+
footer: { component: 'footer' },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
landing: {
|
|
133
|
+
displayName: 'Landing (no nav)',
|
|
134
|
+
config: {
|
|
135
|
+
grid: {
|
|
136
|
+
default: { areas: ['main'] },
|
|
137
|
+
},
|
|
138
|
+
zones: {
|
|
139
|
+
main: { type: 'slot' },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
magazine: {
|
|
144
|
+
displayName: 'Magazine',
|
|
145
|
+
config: {
|
|
146
|
+
grid: {
|
|
147
|
+
default: { areas: ['header', 'main', 'aside', 'footer'], columns: '1fr', rows: 'auto 1fr auto auto' },
|
|
148
|
+
md: { areas: ['header header header', 'main main aside', 'footer footer footer'], columns: '1fr 1fr 300px', rows: 'auto 1fr auto', gap: '24px' },
|
|
149
|
+
},
|
|
150
|
+
zones: {
|
|
151
|
+
header: { component: 'nav-menu' },
|
|
152
|
+
main: { type: 'slot' },
|
|
153
|
+
aside: { component: 'sidebar-menu' },
|
|
154
|
+
footer: { component: 'footer' },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|