@particle-academy/fancy-cms-ui 0.7.0 → 0.8.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/CHANGELOG.md +395 -0
- package/LICENSE +21 -0
- package/agent-guide/professional-pages.md +107 -0
- package/dist/{chunk-YOAZRQKN.js → chunk-IOMIYI45.js} +6 -4
- package/dist/{chunk-YOAZRQKN.js.map → chunk-IOMIYI45.js.map} +1 -1
- package/dist/{chunk-IWQQINCF.js → chunk-SJYKJ6SG.js} +300 -83
- package/dist/chunk-SJYKJ6SG.js.map +1 -0
- package/dist/{chunk-BWGAUTKG.js → chunk-V6QIOJI7.js} +3 -3
- package/dist/{chunk-BWGAUTKG.js.map → chunk-V6QIOJI7.js.map} +1 -1
- package/dist/editor.cjs +313 -94
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.d.cts +2 -2
- package/dist/editor.d.ts +2 -2
- package/dist/editor.js +3 -3
- package/dist/index.cjs +301 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -4
- package/dist/react.cjs +288 -62
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{registry-CiPir27w.d.cts → registry-B4FaQDip.d.cts} +31 -1
- package/dist/{registry-CiPir27w.d.ts → registry-B4FaQDip.d.ts} +31 -1
- package/dist/{useEditor-CoxNeC53.d.cts → useEditor-CIRm2oi-.d.cts} +1 -1
- package/dist/{useEditor-DAE36OYU.d.ts → useEditor-DZDD9qpS.d.ts} +1 -1
- package/package.json +107 -105
- package/dist/chunk-IWQQINCF.js.map +0 -1
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { childrenOf as childrenOf$1, descendantsOf, fractionalKey } from '@particle-academy/fancy-doc-commons';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { useMemo, Fragment } from 'react';
|
|
3
|
+
import { createElement, useMemo, Fragment } from 'react';
|
|
4
4
|
|
|
5
5
|
// src/document/types.ts
|
|
6
6
|
function isBinding(v) {
|
|
7
7
|
return typeof v === "object" && v !== null && typeof v.$bind === "string";
|
|
8
8
|
}
|
|
9
|
+
function hasNodeMap(value) {
|
|
10
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
11
|
+
const nodes = value.nodes;
|
|
12
|
+
return typeof nodes === "object" && nodes !== null && !Array.isArray(nodes);
|
|
13
|
+
}
|
|
9
14
|
var DEFAULT_BREAKPOINTS = {
|
|
10
15
|
base: 0,
|
|
11
16
|
md: 768,
|
|
@@ -21,10 +26,22 @@ function emptyDoc(id, slug = "/") {
|
|
|
21
26
|
nodes: {}
|
|
22
27
|
};
|
|
23
28
|
}
|
|
29
|
+
|
|
30
|
+
// src/document/own.ts
|
|
31
|
+
var has = Object.prototype.hasOwnProperty;
|
|
32
|
+
function own(map, key) {
|
|
33
|
+
return map != null && has.call(map, key) ? map[key] : void 0;
|
|
34
|
+
}
|
|
35
|
+
function setOwn(map, key, value) {
|
|
36
|
+
Object.defineProperty(map, key, { value, writable: true, enumerable: true, configurable: true });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/document/reduce.ts
|
|
24
40
|
function childrenOf(doc, parent) {
|
|
25
41
|
return childrenOf$1(doc, parent);
|
|
26
42
|
}
|
|
27
43
|
function rootIds(doc) {
|
|
44
|
+
if (!hasNodeMap(doc)) return [];
|
|
28
45
|
return childrenOf(doc, null).map((n) => n.id);
|
|
29
46
|
}
|
|
30
47
|
function lastRootId(doc) {
|
|
@@ -35,7 +52,7 @@ function descendantIds(doc, id) {
|
|
|
35
52
|
return descendantsOf(doc, id);
|
|
36
53
|
}
|
|
37
54
|
function patchNode(doc, id, patch) {
|
|
38
|
-
const node = doc.nodes
|
|
55
|
+
const node = own(doc.nodes, id);
|
|
39
56
|
return {
|
|
40
57
|
...doc,
|
|
41
58
|
nodes: { ...doc.nodes, [id]: { ...node, ...patch } },
|
|
@@ -49,8 +66,8 @@ function reduce(doc, op, opts = {}) {
|
|
|
49
66
|
};
|
|
50
67
|
switch (op.t) {
|
|
51
68
|
case "insert_node": {
|
|
52
|
-
if (doc.nodes
|
|
53
|
-
if (op.node.parent !== null && !doc.nodes
|
|
69
|
+
if (own(doc.nodes, op.node.id)) return invalid("node id already exists");
|
|
70
|
+
if (op.node.parent !== null && !own(doc.nodes, op.node.parent)) return invalid("parent not found");
|
|
54
71
|
return {
|
|
55
72
|
...doc,
|
|
56
73
|
nodes: { ...doc.nodes, [op.node.id]: op.node },
|
|
@@ -58,11 +75,11 @@ function reduce(doc, op, opts = {}) {
|
|
|
58
75
|
};
|
|
59
76
|
}
|
|
60
77
|
case "remove_node": {
|
|
61
|
-
if (!doc.nodes
|
|
78
|
+
if (!own(doc.nodes, op.id)) return invalid("node not found");
|
|
62
79
|
const dead = /* @__PURE__ */ new Set([op.id, ...descendantIds(doc, op.id)]);
|
|
63
80
|
const nodes = {};
|
|
64
81
|
for (const id of Object.keys(doc.nodes)) {
|
|
65
|
-
if (!dead.has(id)) nodes
|
|
82
|
+
if (!dead.has(id)) setOwn(nodes, id, own(doc.nodes, id));
|
|
66
83
|
}
|
|
67
84
|
return {
|
|
68
85
|
...doc,
|
|
@@ -71,10 +88,10 @@ function reduce(doc, op, opts = {}) {
|
|
|
71
88
|
};
|
|
72
89
|
}
|
|
73
90
|
case "move_node": {
|
|
74
|
-
const node = doc.nodes
|
|
91
|
+
const node = own(doc.nodes, op.id);
|
|
75
92
|
if (!node) return invalid("node not found");
|
|
76
93
|
if (op.parent === op.id) return invalid("cannot parent a node to itself");
|
|
77
|
-
if (op.parent !== null && !doc.nodes
|
|
94
|
+
if (op.parent !== null && !own(doc.nodes, op.parent)) return invalid("new parent not found");
|
|
78
95
|
if (op.parent !== null && descendantIds(doc, op.id).includes(op.parent)) {
|
|
79
96
|
return invalid("move would create a cycle");
|
|
80
97
|
}
|
|
@@ -85,34 +102,35 @@ function reduce(doc, op, opts = {}) {
|
|
|
85
102
|
};
|
|
86
103
|
}
|
|
87
104
|
case "set_node_props": {
|
|
88
|
-
|
|
105
|
+
const node = own(doc.nodes, op.id);
|
|
106
|
+
if (!node) return invalid("node not found");
|
|
89
107
|
return patchNode(doc, op.id, {
|
|
90
|
-
props: { ...
|
|
108
|
+
props: { ...node.props, ...op.patch }
|
|
91
109
|
});
|
|
92
110
|
}
|
|
93
111
|
case "set_layout": {
|
|
94
|
-
if (!doc.nodes
|
|
112
|
+
if (!own(doc.nodes, op.id)) return invalid("node not found");
|
|
95
113
|
return patchNode(doc, op.id, { layout: op.layout });
|
|
96
114
|
}
|
|
97
115
|
case "set_style": {
|
|
98
|
-
const node = doc.nodes
|
|
116
|
+
const node = own(doc.nodes, op.id);
|
|
99
117
|
if (!node) return invalid("node not found");
|
|
100
|
-
const prev = node.style
|
|
118
|
+
const prev = own(node.style, op.breakpoint) ?? {};
|
|
101
119
|
return patchNode(doc, op.id, {
|
|
102
120
|
style: { ...node.style, [op.breakpoint]: { ...prev, ...op.patch } }
|
|
103
121
|
});
|
|
104
122
|
}
|
|
105
123
|
case "set_constraints": {
|
|
106
|
-
const node = doc.nodes
|
|
124
|
+
const node = own(doc.nodes, op.id);
|
|
107
125
|
if (!node) return invalid("node not found");
|
|
108
126
|
const base = node.constraints ?? { base: { width: "hug", height: "hug" } };
|
|
109
|
-
const prev = base
|
|
127
|
+
const prev = own(base, op.breakpoint) ?? {};
|
|
110
128
|
return patchNode(doc, op.id, {
|
|
111
129
|
constraints: { ...base, [op.breakpoint]: { ...prev, ...op.patch } }
|
|
112
130
|
});
|
|
113
131
|
}
|
|
114
132
|
case "set_animation": {
|
|
115
|
-
const node = doc.nodes
|
|
133
|
+
const node = own(doc.nodes, op.id);
|
|
116
134
|
if (!node) return invalid("node not found");
|
|
117
135
|
const list = node.animations ?? [];
|
|
118
136
|
const idx = list.findIndex((a) => a.id === op.anim.id);
|
|
@@ -121,14 +139,14 @@ function reduce(doc, op, opts = {}) {
|
|
|
121
139
|
});
|
|
122
140
|
}
|
|
123
141
|
case "remove_animation": {
|
|
124
|
-
const node = doc.nodes
|
|
142
|
+
const node = own(doc.nodes, op.id);
|
|
125
143
|
if (!node) return invalid("node not found");
|
|
126
144
|
return patchNode(doc, op.id, {
|
|
127
145
|
animations: (node.animations ?? []).filter((a) => a.id !== op.animId)
|
|
128
146
|
});
|
|
129
147
|
}
|
|
130
148
|
case "set_action": {
|
|
131
|
-
const node = doc.nodes
|
|
149
|
+
const node = own(doc.nodes, op.id);
|
|
132
150
|
if (!node) return invalid("node not found");
|
|
133
151
|
const list = node.actions ?? [];
|
|
134
152
|
let actions;
|
|
@@ -144,13 +162,13 @@ function reduce(doc, op, opts = {}) {
|
|
|
144
162
|
case "reorder_roots": {
|
|
145
163
|
const currentRoots = childrenOf(doc, null);
|
|
146
164
|
const current = new Set(currentRoots.map((n) => n.id));
|
|
147
|
-
const same = op.order.length === currentRoots.length && op.order.every((id) => current.has(id));
|
|
165
|
+
const same = op.order.length === currentRoots.length && new Set(op.order).size === op.order.length && op.order.every((id) => current.has(id));
|
|
148
166
|
if (!same) return invalid("reorder must be a permutation of the current roots");
|
|
149
167
|
const nodes = { ...doc.nodes };
|
|
150
168
|
let prev = null;
|
|
151
169
|
for (const id of op.order) {
|
|
152
170
|
prev = fractionalKey(prev, null);
|
|
153
|
-
nodes
|
|
171
|
+
setOwn(nodes, id, { ...own(nodes, id), order: prev });
|
|
154
172
|
}
|
|
155
173
|
return { ...doc, nodes, seq: doc.seq + 1 };
|
|
156
174
|
}
|
|
@@ -166,17 +184,17 @@ function invert(doc, op) {
|
|
|
166
184
|
case "insert_node":
|
|
167
185
|
return [{ t: "remove_node", id: op.node.id }];
|
|
168
186
|
case "remove_node": {
|
|
169
|
-
const node = doc.nodes
|
|
187
|
+
const node = own(doc.nodes, op.id);
|
|
170
188
|
if (!node) return [];
|
|
171
189
|
const ids = [op.id, ...descendantIds(doc, op.id)];
|
|
172
|
-
const inserts = ids.map((id) => ({ t: "insert_node", node: doc.nodes
|
|
190
|
+
const inserts = ids.map((id) => ({ t: "insert_node", node: own(doc.nodes, id) }));
|
|
173
191
|
if (node.parent === null) {
|
|
174
192
|
inserts.push({ t: "reorder_roots", order: childrenOf(doc, null).map((n) => n.id) });
|
|
175
193
|
}
|
|
176
194
|
return inserts;
|
|
177
195
|
}
|
|
178
196
|
case "move_node": {
|
|
179
|
-
const node = doc.nodes
|
|
197
|
+
const node = own(doc.nodes, op.id);
|
|
180
198
|
if (!node) return [];
|
|
181
199
|
const back = [{ t: "move_node", id: op.id, parent: node.parent, order: node.order }];
|
|
182
200
|
if (node.parent === null) {
|
|
@@ -185,19 +203,19 @@ function invert(doc, op) {
|
|
|
185
203
|
return back;
|
|
186
204
|
}
|
|
187
205
|
case "set_node_props": {
|
|
188
|
-
const node = doc.nodes
|
|
206
|
+
const node = own(doc.nodes, op.id);
|
|
189
207
|
if (!node) return [];
|
|
190
208
|
const prev = {};
|
|
191
209
|
for (const k of Object.keys(op.patch)) prev[k] = node.props[k];
|
|
192
210
|
return [{ t: "set_node_props", id: op.id, patch: prev }];
|
|
193
211
|
}
|
|
194
212
|
case "set_layout": {
|
|
195
|
-
const node = doc.nodes
|
|
213
|
+
const node = own(doc.nodes, op.id);
|
|
196
214
|
if (!node) return [];
|
|
197
215
|
return [{ t: "set_layout", id: op.id, layout: node.layout }];
|
|
198
216
|
}
|
|
199
217
|
case "set_style": {
|
|
200
|
-
const node = doc.nodes
|
|
218
|
+
const node = own(doc.nodes, op.id);
|
|
201
219
|
if (!node) return [];
|
|
202
220
|
const prevBp = node.style[op.breakpoint] ?? {};
|
|
203
221
|
const prev = {};
|
|
@@ -219,17 +237,23 @@ function pick(obj, keys) {
|
|
|
219
237
|
for (const k of keys) out[k] = obj[k];
|
|
220
238
|
return out;
|
|
221
239
|
}
|
|
240
|
+
function normalizeDoc(input) {
|
|
241
|
+
if (hasNodeMap(input)) return input;
|
|
242
|
+
const id = typeof input === "object" && input !== null && !Array.isArray(input) && typeof input.id === "string" ? input.id : "malformed";
|
|
243
|
+
return emptyDoc(id);
|
|
244
|
+
}
|
|
222
245
|
function migrateDocVerbose(input) {
|
|
223
|
-
const
|
|
246
|
+
const normalized = normalizeDoc(input);
|
|
247
|
+
const legacy = normalized;
|
|
224
248
|
const sections = legacy.sections;
|
|
225
249
|
if (!Array.isArray(sections)) {
|
|
226
|
-
return { doc:
|
|
250
|
+
return { doc: normalized, migrated: false, danglingIds: [], unlistedRootIds: [] };
|
|
227
251
|
}
|
|
228
252
|
const danglingIds = [];
|
|
229
253
|
const ordered = [];
|
|
230
254
|
const seen = /* @__PURE__ */ new Set();
|
|
231
255
|
for (const id of sections) {
|
|
232
|
-
if (!
|
|
256
|
+
if (!own(normalized.nodes, id)) {
|
|
233
257
|
danglingIds.push(id);
|
|
234
258
|
continue;
|
|
235
259
|
}
|
|
@@ -237,13 +261,13 @@ function migrateDocVerbose(input) {
|
|
|
237
261
|
seen.add(id);
|
|
238
262
|
ordered.push(id);
|
|
239
263
|
}
|
|
240
|
-
const unlistedRootIds = Object.values(
|
|
264
|
+
const unlistedRootIds = Object.values(normalized.nodes).filter((n) => n.parent === null && !seen.has(n.id)).sort((a, b) => a.order < b.order ? -1 : a.order > b.order ? 1 : 0).map((n) => n.id);
|
|
241
265
|
const finalOrder = [...ordered, ...unlistedRootIds];
|
|
242
|
-
const nodes = { ...
|
|
266
|
+
const nodes = { ...normalized.nodes };
|
|
243
267
|
let prev = null;
|
|
244
268
|
for (const id of finalOrder) {
|
|
245
269
|
const key = fractionalKey(prev, null);
|
|
246
|
-
nodes
|
|
270
|
+
setOwn(nodes, id, { ...own(nodes, id), order: key });
|
|
247
271
|
prev = key;
|
|
248
272
|
}
|
|
249
273
|
const { sections: _dropped, ...rest } = legacy;
|
|
@@ -262,15 +286,36 @@ function needsMigration(input) {
|
|
|
262
286
|
}
|
|
263
287
|
|
|
264
288
|
// src/render/css.ts
|
|
265
|
-
|
|
289
|
+
function cssString(value) {
|
|
290
|
+
let out = "";
|
|
291
|
+
for (const ch of value) {
|
|
292
|
+
const code = ch.codePointAt(0);
|
|
293
|
+
if (ch === "\\" || ch === '"') out += `\\${ch}`;
|
|
294
|
+
else if (code < 32 || code === 127 || ch === "<") out += `\\${code.toString(16)} `;
|
|
295
|
+
else out += ch;
|
|
296
|
+
}
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
299
|
+
var selectorFor = (id) => `[data-cms="${cssString(id)}"]`;
|
|
300
|
+
var UNITS = /* @__PURE__ */ new Set(["px", "%", "vw", "vh", "rem", "fr"]);
|
|
266
301
|
function lengthToCss(len) {
|
|
267
|
-
|
|
302
|
+
if (typeof len !== "object" || len === null) return null;
|
|
303
|
+
const { value, unit } = len;
|
|
304
|
+
if (typeof value !== "number" || !Number.isFinite(value) || typeof unit !== "string" || !UNITS.has(unit)) return null;
|
|
305
|
+
return `${value}${unit}`;
|
|
268
306
|
}
|
|
269
307
|
function sizeToCss(size) {
|
|
270
308
|
if (size === "fill") return "100%";
|
|
271
309
|
if (size === "hug") return "auto";
|
|
272
310
|
return lengthToCss(size);
|
|
273
311
|
}
|
|
312
|
+
function numberToCss(value) {
|
|
313
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : null;
|
|
314
|
+
}
|
|
315
|
+
function putLen(d, props, len) {
|
|
316
|
+
const css = lengthToCss(len);
|
|
317
|
+
if (css !== null) for (const p of props) d[p] = css;
|
|
318
|
+
}
|
|
274
319
|
var ALIGN = {
|
|
275
320
|
start: "flex-start",
|
|
276
321
|
center: "center",
|
|
@@ -284,51 +329,150 @@ var JUSTIFY = {
|
|
|
284
329
|
between: "space-between",
|
|
285
330
|
around: "space-around"
|
|
286
331
|
};
|
|
332
|
+
function safeCssValue(value) {
|
|
333
|
+
if (/[{}<]/.test(value)) return null;
|
|
334
|
+
let depth = 0;
|
|
335
|
+
let quote = null;
|
|
336
|
+
for (const ch of value) {
|
|
337
|
+
if (quote) {
|
|
338
|
+
if (ch === quote) quote = null;
|
|
339
|
+
} else if (ch === '"' || ch === "'") {
|
|
340
|
+
quote = ch;
|
|
341
|
+
} else if (ch === "(") {
|
|
342
|
+
depth++;
|
|
343
|
+
} else if (ch === ")") {
|
|
344
|
+
depth = Math.max(0, depth - 1);
|
|
345
|
+
} else if (ch === ";" && depth === 0) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return value;
|
|
350
|
+
}
|
|
351
|
+
function put(d, prop, value) {
|
|
352
|
+
if (value === void 0) return;
|
|
353
|
+
const safe = safeCssValue(value);
|
|
354
|
+
if (safe !== null) d[prop] = safe;
|
|
355
|
+
}
|
|
356
|
+
var OVERFLOW = /* @__PURE__ */ new Set(["visible", "hidden", "auto"]);
|
|
357
|
+
var TEXT_TRANSFORM = /* @__PURE__ */ new Set(["none", "uppercase", "lowercase", "capitalize"]);
|
|
358
|
+
var BACKGROUND_SIZE = /* @__PURE__ */ new Set(["cover", "contain", "auto"]);
|
|
359
|
+
var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right", "justify"]);
|
|
360
|
+
var DIRECTIONS = /* @__PURE__ */ new Set(["row", "column"]);
|
|
361
|
+
function keyword(map, value) {
|
|
362
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(map, value) ? map[value] : null;
|
|
363
|
+
}
|
|
364
|
+
function inSet(set, value) {
|
|
365
|
+
return typeof value === "string" && set.has(value) ? value : null;
|
|
366
|
+
}
|
|
287
367
|
function styleDecls(style) {
|
|
288
368
|
const d = {};
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (style.
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (style.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (style.
|
|
305
|
-
|
|
306
|
-
if (
|
|
307
|
-
|
|
369
|
+
putLen(d, ["padding"], style.padding);
|
|
370
|
+
putLen(d, ["padding-left", "padding-right"], style.paddingX);
|
|
371
|
+
putLen(d, ["padding-top", "padding-bottom"], style.paddingY);
|
|
372
|
+
putLen(d, ["margin"], style.margin);
|
|
373
|
+
if (style.marginX === "auto") d["margin-left"] = d["margin-right"] = "auto";
|
|
374
|
+
else putLen(d, ["margin-left", "margin-right"], style.marginX);
|
|
375
|
+
putLen(d, ["margin-top", "margin-bottom"], style.marginY);
|
|
376
|
+
putLen(d, ["border-radius"], style.radius);
|
|
377
|
+
putLen(d, ["max-width"], style.maxWidth);
|
|
378
|
+
putLen(d, ["min-height"], style.minHeight);
|
|
379
|
+
put(d, "aspect-ratio", typeof style.aspectRatio === "string" ? style.aspectRatio : void 0);
|
|
380
|
+
if (style.sticky === true) {
|
|
381
|
+
d["position"] = "sticky";
|
|
382
|
+
d["top"] = "0";
|
|
383
|
+
}
|
|
384
|
+
if (typeof style.zIndex === "number" && Number.isFinite(style.zIndex)) d["z-index"] = String(Math.trunc(style.zIndex));
|
|
385
|
+
const overflow = inSet(OVERFLOW, style.overflow);
|
|
386
|
+
if (overflow) d["overflow"] = overflow;
|
|
387
|
+
put(d, "background", typeof style.background === "string" ? style.background : void 0);
|
|
388
|
+
const backgroundSize = inSet(BACKGROUND_SIZE, style.backgroundSize);
|
|
389
|
+
if (backgroundSize) d["background-size"] = backgroundSize;
|
|
390
|
+
put(d, "background-position", typeof style.backgroundPosition === "string" ? style.backgroundPosition : void 0);
|
|
391
|
+
put(d, "color", typeof style.color === "string" ? style.color : void 0);
|
|
392
|
+
const opacity = numberToCss(style.opacity);
|
|
393
|
+
if (opacity !== null) d["opacity"] = opacity;
|
|
394
|
+
put(d, "font-family", typeof style.fontFamily === "string" ? style.fontFamily : void 0);
|
|
395
|
+
putLen(d, ["font-size"], style.fontSize);
|
|
396
|
+
const fontWeight = numberToCss(style.fontWeight);
|
|
397
|
+
if (fontWeight !== null) d["font-weight"] = fontWeight;
|
|
398
|
+
const lineHeight = numberToCss(style.lineHeight);
|
|
399
|
+
if (lineHeight !== null) d["line-height"] = lineHeight;
|
|
400
|
+
const textAlign = inSet(TEXT_ALIGN, style.textAlign);
|
|
401
|
+
if (textAlign) d["text-align"] = textAlign;
|
|
402
|
+
putLen(d, ["letter-spacing"], style.letterSpacing);
|
|
403
|
+
const textTransform = inSet(TEXT_TRANSFORM, style.textTransform);
|
|
404
|
+
if (textTransform) d["text-transform"] = textTransform;
|
|
405
|
+
put(d, "border", typeof style.border === "string" ? style.border : void 0);
|
|
406
|
+
put(d, "box-shadow", typeof style.boxShadow === "string" ? style.boxShadow : void 0);
|
|
407
|
+
put(d, "transform", typeof style.transform === "string" ? style.transform : void 0);
|
|
408
|
+
put(d, "filter", typeof style.filter === "string" ? style.filter : void 0);
|
|
409
|
+
putLen(d, ["gap"], style.gap);
|
|
410
|
+
const align = keyword(ALIGN, style.align);
|
|
411
|
+
if (align) d["align-items"] = align;
|
|
412
|
+
const justify = keyword(JUSTIFY, style.justify);
|
|
413
|
+
if (justify) d["justify-content"] = justify;
|
|
308
414
|
return d;
|
|
309
415
|
}
|
|
310
|
-
function
|
|
416
|
+
function shownDisplay(node) {
|
|
417
|
+
if (node.layout === "stack") return "flex";
|
|
418
|
+
if (node.layout === "grid") return "grid";
|
|
419
|
+
return "block";
|
|
420
|
+
}
|
|
421
|
+
function gridColumns(style) {
|
|
422
|
+
const min = lengthToCss(style.columnMin);
|
|
423
|
+
if (min !== null) return `repeat(auto-fit, minmax(min(${min}, 100%), 1fr))`;
|
|
424
|
+
if (typeof style.columns === "number" && Number.isFinite(style.columns)) return `repeat(${Math.max(1, Math.trunc(style.columns))}, 1fr)`;
|
|
425
|
+
return void 0;
|
|
426
|
+
}
|
|
427
|
+
function containerDecls(node, style, isBase) {
|
|
311
428
|
const d = {};
|
|
312
429
|
if (node.layout === "stack") {
|
|
313
|
-
d["display"] = "flex";
|
|
314
|
-
|
|
430
|
+
if (isBase) d["display"] = "flex";
|
|
431
|
+
const direction = inSet(DIRECTIONS, style.direction);
|
|
432
|
+
if (isBase || direction) d["flex-direction"] = direction ?? "column";
|
|
433
|
+
if (style.wrap !== void 0) d["flex-wrap"] = style.wrap ? "wrap" : "nowrap";
|
|
315
434
|
} else if (node.layout === "grid") {
|
|
316
|
-
d["display"] = "grid";
|
|
317
|
-
|
|
318
|
-
|
|
435
|
+
if (isBase) d["display"] = "grid";
|
|
436
|
+
const cols = gridColumns(style);
|
|
437
|
+
if (isBase || cols !== void 0) d["grid-template-columns"] = cols ?? "repeat(1, 1fr)";
|
|
438
|
+
} else if (node.layout === "free" && isBase) {
|
|
319
439
|
d["position"] = "relative";
|
|
320
440
|
}
|
|
321
441
|
return d;
|
|
322
442
|
}
|
|
443
|
+
function visibilityDecls(node, style, isBase) {
|
|
444
|
+
if (style.hidden === true) return { display: "none" };
|
|
445
|
+
if (style.hidden === false && !isBase) return { display: shownDisplay(node) };
|
|
446
|
+
return {};
|
|
447
|
+
}
|
|
448
|
+
function themeDecls(theme) {
|
|
449
|
+
const d = {};
|
|
450
|
+
const walk = (value, path) => {
|
|
451
|
+
if (typeof value === "string" || typeof value === "number" && Number.isFinite(value)) {
|
|
452
|
+
const key = path.map((p) => p.toLowerCase().replace(/[^a-z0-9-]/g, "")).filter(Boolean).join("-");
|
|
453
|
+
if (key) put(d, `--cms-${key}`, String(value));
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
457
|
+
for (const [k, v] of Object.entries(value)) walk(v, [...path, k]);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
if (typeof theme === "object" && theme !== null && !Array.isArray(theme)) {
|
|
461
|
+
for (const [k, v] of Object.entries(theme)) {
|
|
462
|
+
if (k !== "name") walk(v, [k]);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return d;
|
|
466
|
+
}
|
|
323
467
|
function constraintDecls(c, parentFree) {
|
|
324
468
|
const d = {};
|
|
325
469
|
const transforms = [];
|
|
326
470
|
if (parentFree) {
|
|
327
471
|
d["position"] = "absolute";
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
472
|
+
putLen(d, ["left"], c.left);
|
|
473
|
+
putLen(d, ["right"], c.right);
|
|
474
|
+
putLen(d, ["top"], c.top);
|
|
475
|
+
putLen(d, ["bottom"], c.bottom);
|
|
332
476
|
if (c.centerX) {
|
|
333
477
|
d["left"] = "50%";
|
|
334
478
|
transforms.push("translateX(-50%)");
|
|
@@ -339,13 +483,15 @@ function constraintDecls(c, parentFree) {
|
|
|
339
483
|
}
|
|
340
484
|
if (transforms.length) d["transform"] = transforms.join(" ");
|
|
341
485
|
}
|
|
342
|
-
|
|
343
|
-
if (
|
|
486
|
+
const width = sizeToCss(c.width);
|
|
487
|
+
if (width !== null) d["width"] = width;
|
|
488
|
+
const height = sizeToCss(c.height);
|
|
489
|
+
if (height !== null) d["height"] = height;
|
|
344
490
|
return d;
|
|
345
491
|
}
|
|
346
492
|
function isParentFree(doc, node) {
|
|
347
493
|
if (node.parent === null) return false;
|
|
348
|
-
const parent = doc.nodes
|
|
494
|
+
const parent = own(doc.nodes, node.parent);
|
|
349
495
|
return !parent || parent.layout === void 0 || parent.layout === "free";
|
|
350
496
|
}
|
|
351
497
|
function serializeRule(selector, decls, indent) {
|
|
@@ -357,16 +503,20 @@ ${body}
|
|
|
357
503
|
${indent}}`;
|
|
358
504
|
}
|
|
359
505
|
function emitDocCss(doc) {
|
|
506
|
+
if (!hasNodeMap(doc)) return "";
|
|
360
507
|
const breakpointPx = DEFAULT_BREAKPOINTS;
|
|
361
508
|
const blocks = [];
|
|
509
|
+
const themeRule = serializeRule(":root", themeDecls(doc.theme), "");
|
|
510
|
+
if (themeRule) blocks.push(themeRule);
|
|
362
511
|
for (const id of Object.keys(doc.nodes).sort()) {
|
|
363
512
|
const node = doc.nodes[id];
|
|
364
513
|
const selector = selectorFor(id);
|
|
365
514
|
const parentFree = isParentFree(doc, node);
|
|
366
515
|
const base = {
|
|
367
|
-
...
|
|
516
|
+
...containerDecls(node, node.style.base, true),
|
|
368
517
|
...node.constraints ? constraintDecls(node.constraints.base, parentFree) : {},
|
|
369
|
-
...styleDecls(node.style.base)
|
|
518
|
+
...styleDecls(node.style.base),
|
|
519
|
+
...visibilityDecls(node, node.style.base, true)
|
|
370
520
|
};
|
|
371
521
|
const baseRule = serializeRule(selector, base, "");
|
|
372
522
|
if (baseRule) blocks.push(baseRule);
|
|
@@ -374,9 +524,12 @@ function emitDocCss(doc) {
|
|
|
374
524
|
if (bp === "base") continue;
|
|
375
525
|
const px = breakpointPx[bp];
|
|
376
526
|
if (px === void 0) continue;
|
|
527
|
+
const bpStyle = node.style[bp];
|
|
377
528
|
const decls = {
|
|
529
|
+
...bpStyle ? containerDecls(node, bpStyle, false) : {},
|
|
378
530
|
...node.constraints?.[bp] ? constraintDecls(node.constraints[bp], parentFree) : {},
|
|
379
|
-
...
|
|
531
|
+
...bpStyle ? styleDecls(bpStyle) : {},
|
|
532
|
+
...bpStyle ? visibilityDecls(node, bpStyle, false) : {}
|
|
380
533
|
};
|
|
381
534
|
const inner = serializeRule(selector, decls, " ");
|
|
382
535
|
if (inner) blocks.push(`@media (min-width: ${px}px) {
|
|
@@ -394,6 +547,48 @@ function resolveValue(v, data) {
|
|
|
394
547
|
if (isBinding(v)) return getPath(data, v.$bind);
|
|
395
548
|
return v;
|
|
396
549
|
}
|
|
550
|
+
var LANDMARK_TAGS = ["section", "header", "nav", "main", "footer", "article", "aside", "div"];
|
|
551
|
+
var LANDMARKS = new Set(LANDMARK_TAGS);
|
|
552
|
+
var CONTAINERS = /* @__PURE__ */ new Set(["stack", "grid", "frame", "shape", "card"]);
|
|
553
|
+
var SAFE_SCHEMES = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
|
|
554
|
+
function safeHref(raw) {
|
|
555
|
+
const href = raw.trim();
|
|
556
|
+
if (!href) return null;
|
|
557
|
+
const probe = href.replace(/[\u0000- \u007f]+/g, "");
|
|
558
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(probe);
|
|
559
|
+
if (scheme && !SAFE_SCHEMES.has(scheme[1].toLowerCase())) return null;
|
|
560
|
+
return href;
|
|
561
|
+
}
|
|
562
|
+
var ANCHOR_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
563
|
+
function anchorFor(node, text) {
|
|
564
|
+
const anchor = text(node.props.anchor);
|
|
565
|
+
return ANCHOR_PATTERN.test(anchor) ? anchor : null;
|
|
566
|
+
}
|
|
567
|
+
function elementFor(node, text) {
|
|
568
|
+
const as = text(node.props.as);
|
|
569
|
+
switch (node.type) {
|
|
570
|
+
case "heading": {
|
|
571
|
+
const level = Number(text(node.props.level) || 2);
|
|
572
|
+
return { tag: Number.isInteger(level) && level >= 1 && level <= 6 ? `h${level}` : "h2" };
|
|
573
|
+
}
|
|
574
|
+
case "text":
|
|
575
|
+
return { tag: "p" };
|
|
576
|
+
case "section":
|
|
577
|
+
return { tag: LANDMARKS.has(as) ? as : "section" };
|
|
578
|
+
case "list":
|
|
579
|
+
return { tag: text(node.props.ordered) === "true" ? "ol" : "ul" };
|
|
580
|
+
case "button":
|
|
581
|
+
case "link": {
|
|
582
|
+
const href = safeHref(text(node.props.href));
|
|
583
|
+
if (href === null) return { tag: node.type === "link" ? "span" : "div" };
|
|
584
|
+
const attrs = { href };
|
|
585
|
+
if (/^https?:\/\//i.test(href)) attrs.rel = "noopener noreferrer";
|
|
586
|
+
return { tag: "a", attrs };
|
|
587
|
+
}
|
|
588
|
+
default:
|
|
589
|
+
return { tag: CONTAINERS.has(node.type) && LANDMARKS.has(as) ? as : "div" };
|
|
590
|
+
}
|
|
591
|
+
}
|
|
397
592
|
var defaultRegistry = {
|
|
398
593
|
section: ({ children }) => children,
|
|
399
594
|
stack: ({ children }) => children,
|
|
@@ -406,7 +601,12 @@ var defaultRegistry = {
|
|
|
406
601
|
// Rich text — inline-formatted HTML (gradient spans, links, <code>, …) that
|
|
407
602
|
// plain `text` can't express. The author owns the markup (it's their content).
|
|
408
603
|
richtext: ({ node, text }) => /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: text(node.props.html) } }),
|
|
409
|
-
|
|
604
|
+
// The [data-cms] element is already the <a> (see elementFor), so a link renders its label only.
|
|
605
|
+
link: ({ node, text }) => text(node.props.content) || "link",
|
|
606
|
+
list: ({ node, resolve }) => {
|
|
607
|
+
const items = resolve(node.props.items);
|
|
608
|
+
return Array.isArray(items) ? items.map((item, i) => /* @__PURE__ */ jsx("li", { children: item === null || item === void 0 ? "" : String(item) }, i)) : null;
|
|
609
|
+
},
|
|
410
610
|
divider: () => /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: 0 } }),
|
|
411
611
|
callout: ({ node, text }) => {
|
|
412
612
|
const tone = { info: "#3b82f6", success: "#10b981", warning: "#f59e0b", danger: "#ef4444" }[text(node.props.variant)] ?? "#3b82f6";
|
|
@@ -418,15 +618,20 @@ var defaultRegistry = {
|
|
|
418
618
|
const variant = text(node.props.variant) || "primary";
|
|
419
619
|
return /* @__PURE__ */ jsx("span", { "data-cms-button": variant, style: buttonStyle(variant), children: label });
|
|
420
620
|
},
|
|
421
|
-
image: ({ node, text }) =>
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
621
|
+
image: ({ node, text }) => {
|
|
622
|
+
const fit = text(node.props.fit);
|
|
623
|
+
return /* @__PURE__ */ jsx(
|
|
624
|
+
"img",
|
|
625
|
+
{
|
|
626
|
+
src: text(node.props.src),
|
|
627
|
+
alt: text(node.props.alt),
|
|
628
|
+
loading: text(node.props.loading) === "eager" ? "eager" : "lazy",
|
|
629
|
+
style: { width: "100%", height: "100%", objectFit: IMAGE_FITS.has(fit) ? fit : "cover", display: "block" }
|
|
630
|
+
}
|
|
631
|
+
);
|
|
632
|
+
}
|
|
429
633
|
};
|
|
634
|
+
var IMAGE_FITS = /* @__PURE__ */ new Set(["cover", "contain", "fill", "none", "scale-down"]);
|
|
430
635
|
function buttonStyle(variant) {
|
|
431
636
|
const base = {
|
|
432
637
|
display: "inline-flex",
|
|
@@ -445,7 +650,7 @@ function buttonStyle(variant) {
|
|
|
445
650
|
return { ...base, background: "#7c3aed", color: "#fff", border: "1px solid #7c3aed" };
|
|
446
651
|
}
|
|
447
652
|
function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
448
|
-
const node = doc.nodes
|
|
653
|
+
const node = own(doc.nodes, id);
|
|
449
654
|
if (!node) return null;
|
|
450
655
|
if (node.type === "repeater") {
|
|
451
656
|
const arr = resolveValue(node.props.items, data);
|
|
@@ -461,7 +666,19 @@ function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
|
461
666
|
};
|
|
462
667
|
const renderer = registry[node.type];
|
|
463
668
|
const inner = renderer ? renderer({ node, doc, children: kids, data, resolve, text }) : node.island ? null : kids;
|
|
464
|
-
|
|
669
|
+
const { tag, attrs } = elementFor(node, text);
|
|
670
|
+
const anchor = anchorFor(node, text);
|
|
671
|
+
return createElement(
|
|
672
|
+
tag,
|
|
673
|
+
{
|
|
674
|
+
"data-cms": node.id,
|
|
675
|
+
"data-cms-island": node.island ? node.type : void 0,
|
|
676
|
+
className: node.className,
|
|
677
|
+
...anchor ? { id: anchor } : {},
|
|
678
|
+
...attrs
|
|
679
|
+
},
|
|
680
|
+
inner
|
|
681
|
+
);
|
|
465
682
|
}
|
|
466
683
|
function CmsPage({
|
|
467
684
|
doc: input,
|
|
@@ -476,6 +693,6 @@ function CmsPage({
|
|
|
476
693
|
] });
|
|
477
694
|
}
|
|
478
695
|
|
|
479
|
-
export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds };
|
|
480
|
-
//# sourceMappingURL=chunk-
|
|
481
|
-
//# sourceMappingURL=chunk-
|
|
696
|
+
export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, hasNodeMap, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds };
|
|
697
|
+
//# sourceMappingURL=chunk-SJYKJ6SG.js.map
|
|
698
|
+
//# sourceMappingURL=chunk-SJYKJ6SG.js.map
|