@particle-academy/fancy-cms-ui 0.7.1 → 0.9.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 +448 -0
- package/LICENSE +21 -0
- package/agent-guide/professional-pages.md +107 -0
- package/dist/{chunk-SYRU2X45.js → chunk-BVMSHUQF.js} +6 -4
- package/dist/{chunk-SYRU2X45.js.map → chunk-BVMSHUQF.js.map} +1 -1
- package/dist/chunk-IRG5IKKO.js +716 -0
- package/dist/chunk-IRG5IKKO.js.map +1 -0
- package/dist/{chunk-R7HDS4VG.js → chunk-TJL26EAX.js} +3 -3
- package/dist/{chunk-R7HDS4VG.js.map → chunk-TJL26EAX.js.map} +1 -1
- package/dist/editor.cjs +325 -103
- 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 +335 -110
- 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 +304 -85
- 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-CUNaBqTs.d.cts → registry-F2TAMjhx.d.cts} +33 -1
- package/dist/{registry-CUNaBqTs.d.ts → registry-F2TAMjhx.d.ts} +33 -1
- package/dist/{useEditor-wdlYQMHg.d.cts → useEditor-B2kVZJA0.d.cts} +1 -1
- package/dist/{useEditor-aPH5falI.d.ts → useEditor-BQSictH3.d.ts} +1 -1
- package/package.json +107 -105
- package/dist/chunk-LY6ID2J2.js +0 -494
- package/dist/chunk-LY6ID2J2.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fancyDocCommons = require('@particle-academy/fancy-doc-commons');
|
|
4
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
5
4
|
var react = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
7
|
// src/document/types.ts
|
|
8
8
|
function isBinding(v) {
|
|
@@ -13,6 +13,12 @@ function hasNodeMap(value) {
|
|
|
13
13
|
const nodes = value.nodes;
|
|
14
14
|
return typeof nodes === "object" && nodes !== null && !Array.isArray(nodes);
|
|
15
15
|
}
|
|
16
|
+
function withNodeDefaults(node) {
|
|
17
|
+
const props = typeof node.props === "object" && node.props !== null ? node.props : {};
|
|
18
|
+
const style = typeof node.style === "object" && node.style !== null ? node.style : { base: {} };
|
|
19
|
+
const base = typeof style.base === "object" && style.base !== null ? style.base : {};
|
|
20
|
+
return props === node.props && style === node.style && base === style.base ? node : { ...node, props, style: { ...style, base } };
|
|
21
|
+
}
|
|
16
22
|
var DEFAULT_BREAKPOINTS = {
|
|
17
23
|
base: 0,
|
|
18
24
|
md: 768,
|
|
@@ -61,6 +67,17 @@ function bindingSources(doc) {
|
|
|
61
67
|
}
|
|
62
68
|
return [...seen.values()];
|
|
63
69
|
}
|
|
70
|
+
|
|
71
|
+
// src/document/own.ts
|
|
72
|
+
var has = Object.prototype.hasOwnProperty;
|
|
73
|
+
function own(map, key) {
|
|
74
|
+
return map != null && has.call(map, key) ? map[key] : void 0;
|
|
75
|
+
}
|
|
76
|
+
function setOwn(map, key, value) {
|
|
77
|
+
Object.defineProperty(map, key, { value, writable: true, enumerable: true, configurable: true });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/document/reduce.ts
|
|
64
81
|
function childrenOf(doc, parent) {
|
|
65
82
|
return fancyDocCommons.childrenOf(doc, parent);
|
|
66
83
|
}
|
|
@@ -76,7 +93,7 @@ function descendantIds(doc, id) {
|
|
|
76
93
|
return fancyDocCommons.descendantsOf(doc, id);
|
|
77
94
|
}
|
|
78
95
|
function patchNode(doc, id, patch) {
|
|
79
|
-
const node = doc.nodes
|
|
96
|
+
const node = own(doc.nodes, id);
|
|
80
97
|
return {
|
|
81
98
|
...doc,
|
|
82
99
|
nodes: { ...doc.nodes, [id]: { ...node, ...patch } },
|
|
@@ -90,8 +107,8 @@ function reduce(doc, op, opts = {}) {
|
|
|
90
107
|
};
|
|
91
108
|
switch (op.t) {
|
|
92
109
|
case "insert_node": {
|
|
93
|
-
if (doc.nodes
|
|
94
|
-
if (op.node.parent !== null && !doc.nodes
|
|
110
|
+
if (own(doc.nodes, op.node.id)) return invalid("node id already exists");
|
|
111
|
+
if (op.node.parent !== null && !own(doc.nodes, op.node.parent)) return invalid("parent not found");
|
|
95
112
|
return {
|
|
96
113
|
...doc,
|
|
97
114
|
nodes: { ...doc.nodes, [op.node.id]: op.node },
|
|
@@ -99,11 +116,11 @@ function reduce(doc, op, opts = {}) {
|
|
|
99
116
|
};
|
|
100
117
|
}
|
|
101
118
|
case "remove_node": {
|
|
102
|
-
if (!doc.nodes
|
|
119
|
+
if (!own(doc.nodes, op.id)) return invalid("node not found");
|
|
103
120
|
const dead = /* @__PURE__ */ new Set([op.id, ...descendantIds(doc, op.id)]);
|
|
104
121
|
const nodes = {};
|
|
105
122
|
for (const id of Object.keys(doc.nodes)) {
|
|
106
|
-
if (!dead.has(id)) nodes
|
|
123
|
+
if (!dead.has(id)) setOwn(nodes, id, own(doc.nodes, id));
|
|
107
124
|
}
|
|
108
125
|
return {
|
|
109
126
|
...doc,
|
|
@@ -112,10 +129,10 @@ function reduce(doc, op, opts = {}) {
|
|
|
112
129
|
};
|
|
113
130
|
}
|
|
114
131
|
case "move_node": {
|
|
115
|
-
const node = doc.nodes
|
|
132
|
+
const node = own(doc.nodes, op.id);
|
|
116
133
|
if (!node) return invalid("node not found");
|
|
117
134
|
if (op.parent === op.id) return invalid("cannot parent a node to itself");
|
|
118
|
-
if (op.parent !== null && !doc.nodes
|
|
135
|
+
if (op.parent !== null && !own(doc.nodes, op.parent)) return invalid("new parent not found");
|
|
119
136
|
if (op.parent !== null && descendantIds(doc, op.id).includes(op.parent)) {
|
|
120
137
|
return invalid("move would create a cycle");
|
|
121
138
|
}
|
|
@@ -126,34 +143,35 @@ function reduce(doc, op, opts = {}) {
|
|
|
126
143
|
};
|
|
127
144
|
}
|
|
128
145
|
case "set_node_props": {
|
|
129
|
-
|
|
146
|
+
const node = own(doc.nodes, op.id);
|
|
147
|
+
if (!node) return invalid("node not found");
|
|
130
148
|
return patchNode(doc, op.id, {
|
|
131
|
-
props: { ...
|
|
149
|
+
props: { ...node.props, ...op.patch }
|
|
132
150
|
});
|
|
133
151
|
}
|
|
134
152
|
case "set_layout": {
|
|
135
|
-
if (!doc.nodes
|
|
153
|
+
if (!own(doc.nodes, op.id)) return invalid("node not found");
|
|
136
154
|
return patchNode(doc, op.id, { layout: op.layout });
|
|
137
155
|
}
|
|
138
156
|
case "set_style": {
|
|
139
|
-
const node = doc.nodes
|
|
157
|
+
const node = own(doc.nodes, op.id);
|
|
140
158
|
if (!node) return invalid("node not found");
|
|
141
|
-
const prev = node.style
|
|
159
|
+
const prev = own(node.style, op.breakpoint) ?? {};
|
|
142
160
|
return patchNode(doc, op.id, {
|
|
143
161
|
style: { ...node.style, [op.breakpoint]: { ...prev, ...op.patch } }
|
|
144
162
|
});
|
|
145
163
|
}
|
|
146
164
|
case "set_constraints": {
|
|
147
|
-
const node = doc.nodes
|
|
165
|
+
const node = own(doc.nodes, op.id);
|
|
148
166
|
if (!node) return invalid("node not found");
|
|
149
167
|
const base = node.constraints ?? { base: { width: "hug", height: "hug" } };
|
|
150
|
-
const prev = base
|
|
168
|
+
const prev = own(base, op.breakpoint) ?? {};
|
|
151
169
|
return patchNode(doc, op.id, {
|
|
152
170
|
constraints: { ...base, [op.breakpoint]: { ...prev, ...op.patch } }
|
|
153
171
|
});
|
|
154
172
|
}
|
|
155
173
|
case "set_animation": {
|
|
156
|
-
const node = doc.nodes
|
|
174
|
+
const node = own(doc.nodes, op.id);
|
|
157
175
|
if (!node) return invalid("node not found");
|
|
158
176
|
const list = node.animations ?? [];
|
|
159
177
|
const idx = list.findIndex((a) => a.id === op.anim.id);
|
|
@@ -162,14 +180,14 @@ function reduce(doc, op, opts = {}) {
|
|
|
162
180
|
});
|
|
163
181
|
}
|
|
164
182
|
case "remove_animation": {
|
|
165
|
-
const node = doc.nodes
|
|
183
|
+
const node = own(doc.nodes, op.id);
|
|
166
184
|
if (!node) return invalid("node not found");
|
|
167
185
|
return patchNode(doc, op.id, {
|
|
168
186
|
animations: (node.animations ?? []).filter((a) => a.id !== op.animId)
|
|
169
187
|
});
|
|
170
188
|
}
|
|
171
189
|
case "set_action": {
|
|
172
|
-
const node = doc.nodes
|
|
190
|
+
const node = own(doc.nodes, op.id);
|
|
173
191
|
if (!node) return invalid("node not found");
|
|
174
192
|
const list = node.actions ?? [];
|
|
175
193
|
let actions;
|
|
@@ -185,13 +203,13 @@ function reduce(doc, op, opts = {}) {
|
|
|
185
203
|
case "reorder_roots": {
|
|
186
204
|
const currentRoots = childrenOf(doc, null);
|
|
187
205
|
const current = new Set(currentRoots.map((n) => n.id));
|
|
188
|
-
const same = op.order.length === currentRoots.length && op.order.every((id) => current.has(id));
|
|
206
|
+
const same = op.order.length === currentRoots.length && new Set(op.order).size === op.order.length && op.order.every((id) => current.has(id));
|
|
189
207
|
if (!same) return invalid("reorder must be a permutation of the current roots");
|
|
190
208
|
const nodes = { ...doc.nodes };
|
|
191
209
|
let prev = null;
|
|
192
210
|
for (const id of op.order) {
|
|
193
211
|
prev = fancyDocCommons.fractionalKey(prev, null);
|
|
194
|
-
nodes
|
|
212
|
+
setOwn(nodes, id, { ...own(nodes, id), order: prev });
|
|
195
213
|
}
|
|
196
214
|
return { ...doc, nodes, seq: doc.seq + 1 };
|
|
197
215
|
}
|
|
@@ -207,17 +225,17 @@ function invert(doc, op) {
|
|
|
207
225
|
case "insert_node":
|
|
208
226
|
return [{ t: "remove_node", id: op.node.id }];
|
|
209
227
|
case "remove_node": {
|
|
210
|
-
const node = doc.nodes
|
|
228
|
+
const node = own(doc.nodes, op.id);
|
|
211
229
|
if (!node) return [];
|
|
212
230
|
const ids = [op.id, ...descendantIds(doc, op.id)];
|
|
213
|
-
const inserts = ids.map((id) => ({ t: "insert_node", node: doc.nodes
|
|
231
|
+
const inserts = ids.map((id) => ({ t: "insert_node", node: own(doc.nodes, id) }));
|
|
214
232
|
if (node.parent === null) {
|
|
215
233
|
inserts.push({ t: "reorder_roots", order: childrenOf(doc, null).map((n) => n.id) });
|
|
216
234
|
}
|
|
217
235
|
return inserts;
|
|
218
236
|
}
|
|
219
237
|
case "move_node": {
|
|
220
|
-
const node = doc.nodes
|
|
238
|
+
const node = own(doc.nodes, op.id);
|
|
221
239
|
if (!node) return [];
|
|
222
240
|
const back = [{ t: "move_node", id: op.id, parent: node.parent, order: node.order }];
|
|
223
241
|
if (node.parent === null) {
|
|
@@ -226,19 +244,19 @@ function invert(doc, op) {
|
|
|
226
244
|
return back;
|
|
227
245
|
}
|
|
228
246
|
case "set_node_props": {
|
|
229
|
-
const node = doc.nodes
|
|
247
|
+
const node = own(doc.nodes, op.id);
|
|
230
248
|
if (!node) return [];
|
|
231
249
|
const prev = {};
|
|
232
250
|
for (const k of Object.keys(op.patch)) prev[k] = node.props[k];
|
|
233
251
|
return [{ t: "set_node_props", id: op.id, patch: prev }];
|
|
234
252
|
}
|
|
235
253
|
case "set_layout": {
|
|
236
|
-
const node = doc.nodes
|
|
254
|
+
const node = own(doc.nodes, op.id);
|
|
237
255
|
if (!node) return [];
|
|
238
256
|
return [{ t: "set_layout", id: op.id, layout: node.layout }];
|
|
239
257
|
}
|
|
240
258
|
case "set_style": {
|
|
241
|
-
const node = doc.nodes
|
|
259
|
+
const node = own(doc.nodes, op.id);
|
|
242
260
|
if (!node) return [];
|
|
243
261
|
const prevBp = node.style[op.breakpoint] ?? {};
|
|
244
262
|
const prev = {};
|
|
@@ -276,7 +294,7 @@ function migrateDocVerbose(input2) {
|
|
|
276
294
|
const ordered = [];
|
|
277
295
|
const seen = /* @__PURE__ */ new Set();
|
|
278
296
|
for (const id of sections) {
|
|
279
|
-
if (!normalized.nodes
|
|
297
|
+
if (!own(normalized.nodes, id)) {
|
|
280
298
|
danglingIds.push(id);
|
|
281
299
|
continue;
|
|
282
300
|
}
|
|
@@ -290,7 +308,7 @@ function migrateDocVerbose(input2) {
|
|
|
290
308
|
let prev = null;
|
|
291
309
|
for (const id of finalOrder) {
|
|
292
310
|
const key = fancyDocCommons.fractionalKey(prev, null);
|
|
293
|
-
nodes
|
|
311
|
+
setOwn(nodes, id, { ...own(nodes, id), order: key });
|
|
294
312
|
prev = key;
|
|
295
313
|
}
|
|
296
314
|
const { sections: _dropped, ...rest } = legacy;
|
|
@@ -309,15 +327,58 @@ function needsMigration(input2) {
|
|
|
309
327
|
}
|
|
310
328
|
|
|
311
329
|
// src/render/css.ts
|
|
312
|
-
|
|
330
|
+
function cssString(value) {
|
|
331
|
+
let out = "";
|
|
332
|
+
for (const ch of value) {
|
|
333
|
+
const code = ch.codePointAt(0);
|
|
334
|
+
if (ch === "\\" || ch === '"') out += `\\${ch}`;
|
|
335
|
+
else if (code < 32 || code === 127 || ch === "<") out += `\\${code.toString(16)} `;
|
|
336
|
+
else out += ch;
|
|
337
|
+
}
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
var selectorFor = (id) => `[data-cms="${cssString(id)}"]`;
|
|
341
|
+
var BASE_CSS = [
|
|
342
|
+
"/* fancy-cms base */",
|
|
343
|
+
":where([data-cms]) {\n box-sizing: border-box;\n}",
|
|
344
|
+
":where(h1, h2, h3, h4, h5, h6, p, ul, ol)[data-cms] {\n margin: 0;\n}",
|
|
345
|
+
":where(ul, ol)[data-cms] {\n padding-left: 1.25em;\n}",
|
|
346
|
+
":where(a[data-cms]) {\n color: inherit;\n}",
|
|
347
|
+
":where([data-cms] > img) {\n display: block;\n height: 100%;\n object-fit: cover;\n width: 100%;\n}",
|
|
348
|
+
':where([data-cms] > img[data-cms-fit="contain"]) {\n object-fit: contain;\n}',
|
|
349
|
+
':where([data-cms] > img[data-cms-fit="fill"]) {\n object-fit: fill;\n}',
|
|
350
|
+
':where([data-cms] > img[data-cms-fit="none"]) {\n object-fit: none;\n}',
|
|
351
|
+
':where([data-cms] > img[data-cms-fit="scale-down"]) {\n object-fit: scale-down;\n}',
|
|
352
|
+
":where([data-cms-button]) {\n align-items: center;\n border: 1px solid var(--cms-color-primary, #7c3aed);\n border-radius: 8px;\n cursor: pointer;\n display: inline-flex;\n font-weight: 600;\n gap: 6px;\n justify-content: center;\n line-height: 1.2;\n padding: 10px 18px;\n text-decoration: none;\n}",
|
|
353
|
+
':where([data-cms-button="primary"]) {\n background: var(--cms-color-primary, #7c3aed);\n color: #ffffff;\n}',
|
|
354
|
+
':where([data-cms-button="outline"]) {\n background: transparent;\n color: var(--cms-color-primary, #7c3aed);\n}',
|
|
355
|
+
':where([data-cms-button="ghost"]) {\n background: transparent;\n border-color: currentColor;\n color: inherit;\n}',
|
|
356
|
+
":where([data-cms-callout]) {\n background: #3b82f614;\n border-left: 3px solid #3b82f6;\n border-radius: 10px;\n padding: 12px 14px;\n}",
|
|
357
|
+
':where([data-cms-callout="success"]) {\n background: #10b98114;\n border-left-color: #10b981;\n}',
|
|
358
|
+
':where([data-cms-callout="warning"]) {\n background: #f59e0b14;\n border-left-color: #f59e0b;\n}',
|
|
359
|
+
':where([data-cms-callout="danger"]) {\n background: #ef444414;\n border-left-color: #ef4444;\n}',
|
|
360
|
+
":where([data-cms] > hr) {\n border: none;\n border-top: 1px solid #e2e8f0;\n margin: 0;\n}",
|
|
361
|
+
":where([data-cms] > pre) {\n background: #0b1220;\n border-radius: 10px;\n color: #e2e8f0;\n font-family: ui-monospace, monospace;\n font-size: 13px;\n margin: 0;\n overflow-x: auto;\n padding: 12px 14px;\n}"
|
|
362
|
+
].join("\n\n");
|
|
363
|
+
var UNITS = /* @__PURE__ */ new Set(["px", "%", "vw", "vh", "rem", "fr"]);
|
|
313
364
|
function lengthToCss(len) {
|
|
314
|
-
|
|
365
|
+
if (typeof len !== "object" || len === null) return null;
|
|
366
|
+
const { value, unit } = len;
|
|
367
|
+
if (typeof value !== "number" || !Number.isFinite(value) || typeof unit !== "string" || !UNITS.has(unit)) return null;
|
|
368
|
+
return `${value}${unit}`;
|
|
315
369
|
}
|
|
316
370
|
function sizeToCss(size) {
|
|
317
371
|
if (size === "fill") return "100%";
|
|
318
372
|
if (size === "hug") return "auto";
|
|
319
373
|
return lengthToCss(size);
|
|
320
374
|
}
|
|
375
|
+
function numberToCss(value) {
|
|
376
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : null;
|
|
377
|
+
}
|
|
378
|
+
function putLen(d, props, len) {
|
|
379
|
+
const css = lengthToCss(len);
|
|
380
|
+
if (css !== null) for (const p of props) d[p] = css;
|
|
381
|
+
}
|
|
321
382
|
var ALIGN = {
|
|
322
383
|
start: "flex-start",
|
|
323
384
|
center: "center",
|
|
@@ -331,51 +392,150 @@ var JUSTIFY = {
|
|
|
331
392
|
between: "space-between",
|
|
332
393
|
around: "space-around"
|
|
333
394
|
};
|
|
395
|
+
function safeCssValue(value) {
|
|
396
|
+
if (/[{}<]/.test(value)) return null;
|
|
397
|
+
let depth = 0;
|
|
398
|
+
let quote = null;
|
|
399
|
+
for (const ch of value) {
|
|
400
|
+
if (quote) {
|
|
401
|
+
if (ch === quote) quote = null;
|
|
402
|
+
} else if (ch === '"' || ch === "'") {
|
|
403
|
+
quote = ch;
|
|
404
|
+
} else if (ch === "(") {
|
|
405
|
+
depth++;
|
|
406
|
+
} else if (ch === ")") {
|
|
407
|
+
depth = Math.max(0, depth - 1);
|
|
408
|
+
} else if (ch === ";" && depth === 0) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return value;
|
|
413
|
+
}
|
|
414
|
+
function put(d, prop, value) {
|
|
415
|
+
if (value === void 0) return;
|
|
416
|
+
const safe = safeCssValue(value);
|
|
417
|
+
if (safe !== null) d[prop] = safe;
|
|
418
|
+
}
|
|
419
|
+
var OVERFLOW = /* @__PURE__ */ new Set(["visible", "hidden", "auto"]);
|
|
420
|
+
var TEXT_TRANSFORM = /* @__PURE__ */ new Set(["none", "uppercase", "lowercase", "capitalize"]);
|
|
421
|
+
var BACKGROUND_SIZE = /* @__PURE__ */ new Set(["cover", "contain", "auto"]);
|
|
422
|
+
var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right", "justify"]);
|
|
423
|
+
var DIRECTIONS = /* @__PURE__ */ new Set(["row", "column"]);
|
|
424
|
+
function keyword(map, value) {
|
|
425
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(map, value) ? map[value] : null;
|
|
426
|
+
}
|
|
427
|
+
function inSet(set, value) {
|
|
428
|
+
return typeof value === "string" && set.has(value) ? value : null;
|
|
429
|
+
}
|
|
334
430
|
function styleDecls(style) {
|
|
335
431
|
const d = {};
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (style.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (style.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (style.
|
|
352
|
-
|
|
353
|
-
if (
|
|
354
|
-
|
|
432
|
+
putLen(d, ["padding"], style.padding);
|
|
433
|
+
putLen(d, ["padding-left", "padding-right"], style.paddingX);
|
|
434
|
+
putLen(d, ["padding-top", "padding-bottom"], style.paddingY);
|
|
435
|
+
putLen(d, ["margin"], style.margin);
|
|
436
|
+
if (style.marginX === "auto") d["margin-left"] = d["margin-right"] = "auto";
|
|
437
|
+
else putLen(d, ["margin-left", "margin-right"], style.marginX);
|
|
438
|
+
putLen(d, ["margin-top", "margin-bottom"], style.marginY);
|
|
439
|
+
putLen(d, ["border-radius"], style.radius);
|
|
440
|
+
putLen(d, ["max-width"], style.maxWidth);
|
|
441
|
+
putLen(d, ["min-height"], style.minHeight);
|
|
442
|
+
put(d, "aspect-ratio", typeof style.aspectRatio === "string" ? style.aspectRatio : void 0);
|
|
443
|
+
if (style.sticky === true) {
|
|
444
|
+
d["position"] = "sticky";
|
|
445
|
+
d["top"] = "0";
|
|
446
|
+
}
|
|
447
|
+
if (typeof style.zIndex === "number" && Number.isFinite(style.zIndex)) d["z-index"] = String(Math.trunc(style.zIndex));
|
|
448
|
+
const overflow = inSet(OVERFLOW, style.overflow);
|
|
449
|
+
if (overflow) d["overflow"] = overflow;
|
|
450
|
+
put(d, "background", typeof style.background === "string" ? style.background : void 0);
|
|
451
|
+
const backgroundSize = inSet(BACKGROUND_SIZE, style.backgroundSize);
|
|
452
|
+
if (backgroundSize) d["background-size"] = backgroundSize;
|
|
453
|
+
put(d, "background-position", typeof style.backgroundPosition === "string" ? style.backgroundPosition : void 0);
|
|
454
|
+
put(d, "color", typeof style.color === "string" ? style.color : void 0);
|
|
455
|
+
const opacity = numberToCss(style.opacity);
|
|
456
|
+
if (opacity !== null) d["opacity"] = opacity;
|
|
457
|
+
put(d, "font-family", typeof style.fontFamily === "string" ? style.fontFamily : void 0);
|
|
458
|
+
putLen(d, ["font-size"], style.fontSize);
|
|
459
|
+
const fontWeight = numberToCss(style.fontWeight);
|
|
460
|
+
if (fontWeight !== null) d["font-weight"] = fontWeight;
|
|
461
|
+
const lineHeight = numberToCss(style.lineHeight);
|
|
462
|
+
if (lineHeight !== null) d["line-height"] = lineHeight;
|
|
463
|
+
const textAlign = inSet(TEXT_ALIGN, style.textAlign);
|
|
464
|
+
if (textAlign) d["text-align"] = textAlign;
|
|
465
|
+
putLen(d, ["letter-spacing"], style.letterSpacing);
|
|
466
|
+
const textTransform = inSet(TEXT_TRANSFORM, style.textTransform);
|
|
467
|
+
if (textTransform) d["text-transform"] = textTransform;
|
|
468
|
+
put(d, "border", typeof style.border === "string" ? style.border : void 0);
|
|
469
|
+
put(d, "box-shadow", typeof style.boxShadow === "string" ? style.boxShadow : void 0);
|
|
470
|
+
put(d, "transform", typeof style.transform === "string" ? style.transform : void 0);
|
|
471
|
+
put(d, "filter", typeof style.filter === "string" ? style.filter : void 0);
|
|
472
|
+
putLen(d, ["gap"], style.gap);
|
|
473
|
+
const align = keyword(ALIGN, style.align);
|
|
474
|
+
if (align) d["align-items"] = align;
|
|
475
|
+
const justify = keyword(JUSTIFY, style.justify);
|
|
476
|
+
if (justify) d["justify-content"] = justify;
|
|
355
477
|
return d;
|
|
356
478
|
}
|
|
357
|
-
function
|
|
479
|
+
function shownDisplay(node) {
|
|
480
|
+
if (node.layout === "stack") return "flex";
|
|
481
|
+
if (node.layout === "grid") return "grid";
|
|
482
|
+
return "block";
|
|
483
|
+
}
|
|
484
|
+
function gridColumns(style) {
|
|
485
|
+
const min = lengthToCss(style.columnMin);
|
|
486
|
+
if (min !== null) return `repeat(auto-fit, minmax(min(${min}, 100%), 1fr))`;
|
|
487
|
+
if (typeof style.columns === "number" && Number.isFinite(style.columns)) return `repeat(${Math.max(1, Math.trunc(style.columns))}, 1fr)`;
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
function containerDecls(node, style, isBase) {
|
|
358
491
|
const d = {};
|
|
359
492
|
if (node.layout === "stack") {
|
|
360
|
-
d["display"] = "flex";
|
|
361
|
-
|
|
493
|
+
if (isBase) d["display"] = "flex";
|
|
494
|
+
const direction = inSet(DIRECTIONS, style.direction);
|
|
495
|
+
if (isBase || direction) d["flex-direction"] = direction ?? "column";
|
|
496
|
+
if (style.wrap !== void 0) d["flex-wrap"] = style.wrap ? "wrap" : "nowrap";
|
|
362
497
|
} else if (node.layout === "grid") {
|
|
363
|
-
d["display"] = "grid";
|
|
364
|
-
|
|
365
|
-
|
|
498
|
+
if (isBase) d["display"] = "grid";
|
|
499
|
+
const cols = gridColumns(style);
|
|
500
|
+
if (isBase || cols !== void 0) d["grid-template-columns"] = cols ?? "repeat(1, 1fr)";
|
|
501
|
+
} else if (node.layout === "free" && isBase) {
|
|
366
502
|
d["position"] = "relative";
|
|
367
503
|
}
|
|
368
504
|
return d;
|
|
369
505
|
}
|
|
506
|
+
function visibilityDecls(node, style, isBase) {
|
|
507
|
+
if (style.hidden === true) return { display: "none" };
|
|
508
|
+
if (style.hidden === false && !isBase) return { display: shownDisplay(node) };
|
|
509
|
+
return {};
|
|
510
|
+
}
|
|
511
|
+
function themeDecls(theme) {
|
|
512
|
+
const d = {};
|
|
513
|
+
const walk = (value, path) => {
|
|
514
|
+
if (typeof value === "string" || typeof value === "number" && Number.isFinite(value)) {
|
|
515
|
+
const key = path.map((p) => p.toLowerCase().replace(/[^a-z0-9-]/g, "")).filter(Boolean).join("-");
|
|
516
|
+
if (key) put(d, `--cms-${key}`, String(value));
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
520
|
+
for (const [k, v] of Object.entries(value)) walk(v, [...path, k]);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
if (typeof theme === "object" && theme !== null && !Array.isArray(theme)) {
|
|
524
|
+
for (const [k, v] of Object.entries(theme)) {
|
|
525
|
+
if (k !== "name") walk(v, [k]);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return d;
|
|
529
|
+
}
|
|
370
530
|
function constraintDecls(c, parentFree) {
|
|
371
531
|
const d = {};
|
|
372
532
|
const transforms = [];
|
|
373
533
|
if (parentFree) {
|
|
374
534
|
d["position"] = "absolute";
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
535
|
+
putLen(d, ["left"], c.left);
|
|
536
|
+
putLen(d, ["right"], c.right);
|
|
537
|
+
putLen(d, ["top"], c.top);
|
|
538
|
+
putLen(d, ["bottom"], c.bottom);
|
|
379
539
|
if (c.centerX) {
|
|
380
540
|
d["left"] = "50%";
|
|
381
541
|
transforms.push("translateX(-50%)");
|
|
@@ -386,13 +546,15 @@ function constraintDecls(c, parentFree) {
|
|
|
386
546
|
}
|
|
387
547
|
if (transforms.length) d["transform"] = transforms.join(" ");
|
|
388
548
|
}
|
|
389
|
-
|
|
390
|
-
if (
|
|
549
|
+
const width = sizeToCss(c.width);
|
|
550
|
+
if (width !== null) d["width"] = width;
|
|
551
|
+
const height = sizeToCss(c.height);
|
|
552
|
+
if (height !== null) d["height"] = height;
|
|
391
553
|
return d;
|
|
392
554
|
}
|
|
393
555
|
function isParentFree(doc, node) {
|
|
394
556
|
if (node.parent === null) return false;
|
|
395
|
-
const parent = doc.nodes
|
|
557
|
+
const parent = own(doc.nodes, node.parent);
|
|
396
558
|
return !parent || parent.layout === void 0 || parent.layout === "free";
|
|
397
559
|
}
|
|
398
560
|
function serializeRule(selector, decls, indent) {
|
|
@@ -407,24 +569,31 @@ function emitDocCss(doc) {
|
|
|
407
569
|
if (!hasNodeMap(doc)) return "";
|
|
408
570
|
const breakpointPx = DEFAULT_BREAKPOINTS;
|
|
409
571
|
const blocks = [];
|
|
572
|
+
const themeRule = serializeRule(":root", themeDecls(doc.theme), "");
|
|
573
|
+
if (themeRule) blocks.push(themeRule);
|
|
410
574
|
for (const id of Object.keys(doc.nodes).sort()) {
|
|
411
|
-
const node = doc.nodes[id];
|
|
575
|
+
const node = withNodeDefaults(doc.nodes[id]);
|
|
412
576
|
const selector = selectorFor(id);
|
|
413
577
|
const parentFree = isParentFree(doc, node);
|
|
414
578
|
const base = {
|
|
415
|
-
...
|
|
579
|
+
...containerDecls(node, node.style.base, true),
|
|
416
580
|
...node.constraints ? constraintDecls(node.constraints.base, parentFree) : {},
|
|
417
|
-
...styleDecls(node.style.base)
|
|
581
|
+
...styleDecls(node.style.base),
|
|
582
|
+
...visibilityDecls(node, node.style.base, true)
|
|
418
583
|
};
|
|
419
584
|
const baseRule = serializeRule(selector, base, "");
|
|
420
585
|
if (baseRule) blocks.push(baseRule);
|
|
421
586
|
for (const bp of doc.breakpoints) {
|
|
422
587
|
if (bp === "base") continue;
|
|
423
|
-
const px = breakpointPx
|
|
424
|
-
if (px
|
|
588
|
+
const px = own(breakpointPx, bp);
|
|
589
|
+
if (typeof px !== "number") continue;
|
|
590
|
+
const bpStyle = own(node.style, bp);
|
|
591
|
+
const bpConstraints = node.constraints ? own(node.constraints, bp) : void 0;
|
|
425
592
|
const decls = {
|
|
426
|
-
...
|
|
427
|
-
...
|
|
593
|
+
...bpStyle ? containerDecls(node, bpStyle, false) : {},
|
|
594
|
+
...bpConstraints ? constraintDecls(bpConstraints, parentFree) : {},
|
|
595
|
+
...bpStyle ? styleDecls(bpStyle) : {},
|
|
596
|
+
...bpStyle ? visibilityDecls(node, bpStyle, false) : {}
|
|
428
597
|
};
|
|
429
598
|
const inner = serializeRule(selector, decls, " ");
|
|
430
599
|
if (inner) blocks.push(`@media (min-width: ${px}px) {
|
|
@@ -432,7 +601,8 @@ ${inner}
|
|
|
432
601
|
}`);
|
|
433
602
|
}
|
|
434
603
|
}
|
|
435
|
-
|
|
604
|
+
if (blocks.length === 0 && Object.keys(doc.nodes).length === 0) return "";
|
|
605
|
+
return [BASE_CSS, ...blocks].join("\n\n") + "\n";
|
|
436
606
|
}
|
|
437
607
|
function getPath(data, path) {
|
|
438
608
|
return path.split(".").reduce((o, k) => o == null ? void 0 : o[k], data);
|
|
@@ -442,6 +612,55 @@ function resolveValue(v, data) {
|
|
|
442
612
|
if (isBinding(v)) return getPath(data, v.$bind);
|
|
443
613
|
return v;
|
|
444
614
|
}
|
|
615
|
+
var LANDMARK_TAGS = ["section", "header", "nav", "main", "footer", "article", "aside", "div"];
|
|
616
|
+
var LANDMARKS = new Set(LANDMARK_TAGS);
|
|
617
|
+
var CONTAINERS = /* @__PURE__ */ new Set(["stack", "grid", "frame", "shape", "card"]);
|
|
618
|
+
var SAFE_SCHEMES = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
|
|
619
|
+
function safeHref(raw) {
|
|
620
|
+
const href = raw.trim();
|
|
621
|
+
if (!href) return null;
|
|
622
|
+
const probe = href.replace(/[\u0000- \u007f]+/g, "");
|
|
623
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(probe);
|
|
624
|
+
if (scheme && !SAFE_SCHEMES.has(scheme[1].toLowerCase())) return null;
|
|
625
|
+
return href;
|
|
626
|
+
}
|
|
627
|
+
var ANCHOR_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
628
|
+
function anchorFor(node, text) {
|
|
629
|
+
const anchor = text(node.props.anchor);
|
|
630
|
+
return ANCHOR_PATTERN.test(anchor) ? anchor : null;
|
|
631
|
+
}
|
|
632
|
+
function elementFor(node, text) {
|
|
633
|
+
const as = text(node.props.as);
|
|
634
|
+
switch (node.type) {
|
|
635
|
+
case "heading": {
|
|
636
|
+
const level = Number(text(node.props.level) || 2);
|
|
637
|
+
return { tag: Number.isInteger(level) && level >= 1 && level <= 6 ? `h${level}` : "h2" };
|
|
638
|
+
}
|
|
639
|
+
case "text":
|
|
640
|
+
return { tag: "p" };
|
|
641
|
+
case "section":
|
|
642
|
+
return { tag: LANDMARKS.has(as) ? as : "section" };
|
|
643
|
+
case "list":
|
|
644
|
+
return { tag: text(node.props.ordered) === "true" ? "ol" : "ul" };
|
|
645
|
+
case "button":
|
|
646
|
+
case "link": {
|
|
647
|
+
const href = safeHref(text(node.props.href));
|
|
648
|
+
const attrs = {};
|
|
649
|
+
if (href !== null) {
|
|
650
|
+
attrs.href = href;
|
|
651
|
+
if (/^https?:\/\//i.test(href)) attrs.rel = "noopener noreferrer";
|
|
652
|
+
}
|
|
653
|
+
if (node.type === "button") attrs["data-cms-button"] = BUTTON_VARIANTS.has(text(node.props.variant)) ? text(node.props.variant) : "primary";
|
|
654
|
+
return { tag: href !== null ? "a" : node.type === "link" ? "span" : "div", attrs };
|
|
655
|
+
}
|
|
656
|
+
case "callout": {
|
|
657
|
+
const variant = text(node.props.variant);
|
|
658
|
+
return { tag: "div", attrs: { "data-cms-callout": CALLOUT_VARIANTS.has(variant) ? variant : "info" } };
|
|
659
|
+
}
|
|
660
|
+
default:
|
|
661
|
+
return { tag: CONTAINERS.has(node.type) && LANDMARKS.has(as) ? as : "div" };
|
|
662
|
+
}
|
|
663
|
+
}
|
|
445
664
|
var defaultRegistry = {
|
|
446
665
|
section: ({ children }) => children,
|
|
447
666
|
stack: ({ children }) => children,
|
|
@@ -454,47 +673,38 @@ var defaultRegistry = {
|
|
|
454
673
|
// Rich text — inline-formatted HTML (gradient spans, links, <code>, …) that
|
|
455
674
|
// plain `text` can't express. The author owns the markup (it's their content).
|
|
456
675
|
richtext: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: text(node.props.html) } }),
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const
|
|
461
|
-
return
|
|
462
|
-
},
|
|
463
|
-
code: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { margin: 0, padding: "12px 14px", borderRadius: 10, background: "#0b1220", color: "#e2e8f0", fontFamily: "ui-monospace, monospace", fontSize: 13, overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: text(node.props.content) }) }),
|
|
464
|
-
button: ({ node, text }) => {
|
|
465
|
-
const label2 = text(node.props.label) || text(node.props.content) || "Button";
|
|
466
|
-
const variant = text(node.props.variant) || "primary";
|
|
467
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cms-button": variant, style: buttonStyle(variant), children: label2 });
|
|
676
|
+
// The [data-cms] element is already the <a> (see elementFor), so a link renders its label only.
|
|
677
|
+
link: ({ node, text }) => text(node.props.content) || "link",
|
|
678
|
+
list: ({ node, resolve }) => {
|
|
679
|
+
const items = resolve(node.props.items);
|
|
680
|
+
return Array.isArray(items) ? items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: item === null || item === void 0 ? "" : String(item) }, i)) : null;
|
|
468
681
|
},
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
682
|
+
// Looks come from the base stylesheet (render/css.ts BASE_CSS), never from
|
|
683
|
+
// inline style objects, so the PHP renderer emits the same markup.
|
|
684
|
+
divider: () => /* @__PURE__ */ jsxRuntime.jsx("hr", {}),
|
|
685
|
+
callout: ({ node, text }) => text(node.props.content) || "Callout",
|
|
686
|
+
code: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("pre", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: text(node.props.content) }) }),
|
|
687
|
+
button: ({ node, text }) => text(node.props.label) || text(node.props.content) || "Button",
|
|
688
|
+
image: ({ node, text }) => {
|
|
689
|
+
const fit = text(node.props.fit);
|
|
690
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
691
|
+
"img",
|
|
692
|
+
{
|
|
693
|
+
src: text(node.props.src) || void 0,
|
|
694
|
+
alt: text(node.props.alt),
|
|
695
|
+
loading: text(node.props.loading) === "eager" ? "eager" : "lazy",
|
|
696
|
+
"data-cms-fit": IMAGE_FITS.has(fit) && fit !== "cover" ? fit : void 0
|
|
697
|
+
}
|
|
698
|
+
);
|
|
699
|
+
}
|
|
477
700
|
};
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
alignItems: "center",
|
|
482
|
-
gap: 6,
|
|
483
|
-
padding: "9px 16px",
|
|
484
|
-
borderRadius: 8,
|
|
485
|
-
fontWeight: 600,
|
|
486
|
-
fontSize: 14,
|
|
487
|
-
lineHeight: 1,
|
|
488
|
-
cursor: "pointer",
|
|
489
|
-
userSelect: "none"
|
|
490
|
-
};
|
|
491
|
-
if (variant === "ghost") return { ...base, background: "transparent", color: "inherit", border: "1px solid currentColor" };
|
|
492
|
-
if (variant === "outline") return { ...base, background: "transparent", color: "#7c3aed", border: "1px solid #7c3aed" };
|
|
493
|
-
return { ...base, background: "#7c3aed", color: "#fff", border: "1px solid #7c3aed" };
|
|
494
|
-
}
|
|
701
|
+
var IMAGE_FITS = /* @__PURE__ */ new Set(["cover", "contain", "fill", "none", "scale-down"]);
|
|
702
|
+
var BUTTON_VARIANTS = /* @__PURE__ */ new Set(["primary", "outline", "ghost"]);
|
|
703
|
+
var CALLOUT_VARIANTS = /* @__PURE__ */ new Set(["info", "success", "warning", "danger"]);
|
|
495
704
|
function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
496
|
-
const
|
|
497
|
-
if (!
|
|
705
|
+
const stored = own(doc.nodes, id);
|
|
706
|
+
if (!stored) return null;
|
|
707
|
+
const node = withNodeDefaults(stored);
|
|
498
708
|
if (node.type === "repeater") {
|
|
499
709
|
const arr = resolveValue(node.props.items, data);
|
|
500
710
|
const items = Array.isArray(arr) ? arr : [];
|
|
@@ -509,7 +719,19 @@ function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
|
509
719
|
};
|
|
510
720
|
const renderer = registry[node.type];
|
|
511
721
|
const inner = renderer ? renderer({ node, doc, children: kids, data, resolve, text }) : node.island ? null : kids;
|
|
512
|
-
|
|
722
|
+
const { tag, attrs } = elementFor(node, text);
|
|
723
|
+
const anchor = anchorFor(node, text);
|
|
724
|
+
return react.createElement(
|
|
725
|
+
tag,
|
|
726
|
+
{
|
|
727
|
+
"data-cms": node.id,
|
|
728
|
+
"data-cms-island": node.island ? node.type : void 0,
|
|
729
|
+
className: node.className,
|
|
730
|
+
...anchor ? { id: anchor } : {},
|
|
731
|
+
...attrs
|
|
732
|
+
},
|
|
733
|
+
inner
|
|
734
|
+
);
|
|
513
735
|
}
|
|
514
736
|
function CmsPage({
|
|
515
737
|
doc: input2,
|
|
@@ -911,7 +1133,8 @@ var ADD_DEFAULTS = {
|
|
|
911
1133
|
divider: { type: "divider", props: {}, style: {} },
|
|
912
1134
|
code: { type: "code", props: { content: "npm install @particle-academy/react-fancy", lang: "bash" }, style: {} },
|
|
913
1135
|
richtext: { type: "richtext", props: { html: "<p>Rich <strong>text</strong> with <em>inline</em> formatting.</p>" }, style: {} },
|
|
914
|
-
repeater: { type: "repeater", props: { items: "" }, style: { gap: { value: 12, unit: "px" } }, layout: "stack" }
|
|
1136
|
+
repeater: { type: "repeater", props: { items: "" }, style: { gap: { value: 12, unit: "px" } }, layout: "stack" },
|
|
1137
|
+
list: { type: "list", props: { items: ["First point", "Second point"], ordered: false }, style: {} }
|
|
915
1138
|
};
|
|
916
1139
|
var ADD_MENU = [
|
|
917
1140
|
{ kind: "heading", label: "Heading" },
|
|
@@ -927,6 +1150,7 @@ var ADD_MENU = [
|
|
|
927
1150
|
{ kind: "divider", label: "Divider" },
|
|
928
1151
|
{ kind: "code", label: "Code" },
|
|
929
1152
|
{ kind: "richtext", label: "Rich text" },
|
|
1153
|
+
{ kind: "list", label: "List" },
|
|
930
1154
|
{ kind: "repeater", label: "Repeater" }
|
|
931
1155
|
];
|
|
932
1156
|
function resolveInsertParent(doc, selectedId) {
|
|
@@ -1149,5 +1373,6 @@ exports.resolveInsertParent = resolveInsertParent;
|
|
|
1149
1373
|
exports.resolveValue = resolveValue;
|
|
1150
1374
|
exports.rootIds = rootIds;
|
|
1151
1375
|
exports.useEditor = useEditor;
|
|
1376
|
+
exports.withNodeDefaults = withNodeDefaults;
|
|
1152
1377
|
//# sourceMappingURL=index.cjs.map
|
|
1153
1378
|
//# sourceMappingURL=index.cjs.map
|