@particle-academy/fancy-cms-ui 0.7.1 → 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-SYRU2X45.js → chunk-IOMIYI45.js} +6 -4
- package/dist/{chunk-SYRU2X45.js.map → chunk-IOMIYI45.js.map} +1 -1
- package/dist/{chunk-LY6ID2J2.js → chunk-SJYKJ6SG.js} +282 -78
- package/dist/chunk-SJYKJ6SG.js.map +1 -0
- package/dist/{chunk-R7HDS4VG.js → chunk-V6QIOJI7.js} +3 -3
- package/dist/{chunk-R7HDS4VG.js.map → chunk-V6QIOJI7.js.map} +1 -1
- package/dist/editor.cjs +274 -70
- 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 +283 -77
- 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 +253 -52
- 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-B4FaQDip.d.cts} +26 -0
- package/dist/{registry-CUNaBqTs.d.ts → registry-B4FaQDip.d.ts} +26 -0
- package/dist/{useEditor-wdlYQMHg.d.cts → useEditor-CIRm2oi-.d.cts} +1 -1
- package/dist/{useEditor-aPH5falI.d.ts → useEditor-DZDD9qpS.d.ts} +1 -1
- package/package.json +107 -105
- package/dist/chunk-LY6ID2J2.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as Binding, P as PageDoc, m as NodeId, N as Node, J as Json, q as StyleProps, L as LayoutMode } from './registry-
|
|
2
|
-
export { A as Action, a as ActionEvent, b as ActionHandler, c as Anim, d as AnimDriver, e as Bound, f as Breakpoint, C as Constraints, D as DEFAULT_BREAKPOINTS, g as DataContext, E as ElementContext, h as ElementRegistry, i as ElementRenderer, K as Keyframe, j as LegacyPageDoc, k as Length, l as LengthUnit, M as MigrateResult, n as PageMeta, o as PerBreakpoint, S as ScrollMode, p as SizeMode, T as ThemeTokens, r as defaultRegistry, s as emptyDoc, t as getPath, u as hasNodeMap, v as isBinding, w as migrateDoc, x as migrateDocVerbose, y as needsMigration, z as resolveValue } from './registry-
|
|
3
|
-
import { P as PageOp } from './useEditor-
|
|
4
|
-
export { A as Actor, C as Canvas, a as CanvasProps, E as Editor, b as EditorAction, c as EditorApi, d as EditorProps, e as EditorState, I as Inspector, f as InspectorProps, L as LayersPanel, g as LayersPanelProps, O as OpEnvelope, h as PageOpType, i as editorReduce, j as initEditor, u as useEditor } from './useEditor-
|
|
1
|
+
import { B as Binding, P as PageDoc, m as NodeId, N as Node, J as Json, q as StyleProps, L as LayoutMode } from './registry-B4FaQDip.cjs';
|
|
2
|
+
export { A as Action, a as ActionEvent, b as ActionHandler, c as Anim, d as AnimDriver, e as Bound, f as Breakpoint, C as Constraints, D as DEFAULT_BREAKPOINTS, g as DataContext, E as ElementContext, h as ElementRegistry, i as ElementRenderer, K as Keyframe, j as LegacyPageDoc, k as Length, l as LengthUnit, M as MigrateResult, n as PageMeta, o as PerBreakpoint, S as ScrollMode, p as SizeMode, T as ThemeTokens, r as defaultRegistry, s as emptyDoc, t as getPath, u as hasNodeMap, v as isBinding, w as migrateDoc, x as migrateDocVerbose, y as needsMigration, z as resolveValue } from './registry-B4FaQDip.cjs';
|
|
3
|
+
import { P as PageOp } from './useEditor-CIRm2oi-.cjs';
|
|
4
|
+
export { A as Actor, C as Canvas, a as CanvasProps, E as Editor, b as EditorAction, c as EditorApi, d as EditorProps, e as EditorState, I as Inspector, f as InspectorProps, L as LayersPanel, g as LayersPanelProps, O as OpEnvelope, h as PageOpType, i as editorReduce, j as initEditor, u as useEditor } from './useEditor-CIRm2oi-.cjs';
|
|
5
5
|
export { fractionalKey, fractionalKey as keyBetween } from '@particle-academy/fancy-doc-commons';
|
|
6
6
|
export { CmsPage, CmsPageProps, CmsRegion, CmsRegionProps, RenderNode, RenderNodeProps } from './react.cjs';
|
|
7
7
|
import 'react';
|
|
@@ -120,7 +120,7 @@ declare function emitDocCss(doc: PageDoc): string;
|
|
|
120
120
|
*/
|
|
121
121
|
/** Node types that accept children, so an insert lands *inside* them. */
|
|
122
122
|
declare const CONTAINER_TYPES: Set<string>;
|
|
123
|
-
type AddKind = "text" | "heading" | "button" | "link" | "image" | "box" | "stack" | "grid" | "card" | "callout" | "divider" | "code" | "richtext" | "repeater";
|
|
123
|
+
type AddKind = "text" | "heading" | "button" | "link" | "image" | "box" | "stack" | "grid" | "card" | "callout" | "divider" | "code" | "richtext" | "repeater" | "list";
|
|
124
124
|
declare const ADD_DEFAULTS: Record<AddKind, {
|
|
125
125
|
type: string;
|
|
126
126
|
props: Record<string, Json>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as Binding, P as PageDoc, m as NodeId, N as Node, J as Json, q as StyleProps, L as LayoutMode } from './registry-
|
|
2
|
-
export { A as Action, a as ActionEvent, b as ActionHandler, c as Anim, d as AnimDriver, e as Bound, f as Breakpoint, C as Constraints, D as DEFAULT_BREAKPOINTS, g as DataContext, E as ElementContext, h as ElementRegistry, i as ElementRenderer, K as Keyframe, j as LegacyPageDoc, k as Length, l as LengthUnit, M as MigrateResult, n as PageMeta, o as PerBreakpoint, S as ScrollMode, p as SizeMode, T as ThemeTokens, r as defaultRegistry, s as emptyDoc, t as getPath, u as hasNodeMap, v as isBinding, w as migrateDoc, x as migrateDocVerbose, y as needsMigration, z as resolveValue } from './registry-
|
|
3
|
-
import { P as PageOp } from './useEditor-
|
|
4
|
-
export { A as Actor, C as Canvas, a as CanvasProps, E as Editor, b as EditorAction, c as EditorApi, d as EditorProps, e as EditorState, I as Inspector, f as InspectorProps, L as LayersPanel, g as LayersPanelProps, O as OpEnvelope, h as PageOpType, i as editorReduce, j as initEditor, u as useEditor } from './useEditor-
|
|
1
|
+
import { B as Binding, P as PageDoc, m as NodeId, N as Node, J as Json, q as StyleProps, L as LayoutMode } from './registry-B4FaQDip.js';
|
|
2
|
+
export { A as Action, a as ActionEvent, b as ActionHandler, c as Anim, d as AnimDriver, e as Bound, f as Breakpoint, C as Constraints, D as DEFAULT_BREAKPOINTS, g as DataContext, E as ElementContext, h as ElementRegistry, i as ElementRenderer, K as Keyframe, j as LegacyPageDoc, k as Length, l as LengthUnit, M as MigrateResult, n as PageMeta, o as PerBreakpoint, S as ScrollMode, p as SizeMode, T as ThemeTokens, r as defaultRegistry, s as emptyDoc, t as getPath, u as hasNodeMap, v as isBinding, w as migrateDoc, x as migrateDocVerbose, y as needsMigration, z as resolveValue } from './registry-B4FaQDip.js';
|
|
3
|
+
import { P as PageOp } from './useEditor-DZDD9qpS.js';
|
|
4
|
+
export { A as Actor, C as Canvas, a as CanvasProps, E as Editor, b as EditorAction, c as EditorApi, d as EditorProps, e as EditorState, I as Inspector, f as InspectorProps, L as LayersPanel, g as LayersPanelProps, O as OpEnvelope, h as PageOpType, i as editorReduce, j as initEditor, u as useEditor } from './useEditor-DZDD9qpS.js';
|
|
5
5
|
export { fractionalKey, fractionalKey as keyBetween } from '@particle-academy/fancy-doc-commons';
|
|
6
6
|
export { CmsPage, CmsPageProps, CmsRegion, CmsRegionProps, RenderNode, RenderNodeProps } from './react.js';
|
|
7
7
|
import 'react';
|
|
@@ -120,7 +120,7 @@ declare function emitDocCss(doc: PageDoc): string;
|
|
|
120
120
|
*/
|
|
121
121
|
/** Node types that accept children, so an insert lands *inside* them. */
|
|
122
122
|
declare const CONTAINER_TYPES: Set<string>;
|
|
123
|
-
type AddKind = "text" | "heading" | "button" | "link" | "image" | "box" | "stack" | "grid" | "card" | "callout" | "divider" | "code" | "richtext" | "repeater";
|
|
123
|
+
type AddKind = "text" | "heading" | "button" | "link" | "image" | "box" | "stack" | "grid" | "card" | "callout" | "divider" | "code" | "richtext" | "repeater" | "list";
|
|
124
124
|
declare const ADD_DEFAULTS: Record<AddKind, {
|
|
125
125
|
type: string;
|
|
126
126
|
props: Record<string, Json>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { CmsRegion } from './chunk-
|
|
2
|
-
export { ADD_DEFAULTS, ADD_MENU, CONTAINER_TYPES, Canvas, Editor, Inspector, LayersPanel, buildInsertOp, editorReduce, initEditor, resolveInsertParent, useEditor } from './chunk-
|
|
3
|
-
import { isBinding } from './chunk-
|
|
4
|
-
export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, hasNodeMap, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds } from './chunk-
|
|
1
|
+
export { CmsRegion } from './chunk-V6QIOJI7.js';
|
|
2
|
+
export { ADD_DEFAULTS, ADD_MENU, CONTAINER_TYPES, Canvas, Editor, Inspector, LayersPanel, buildInsertOp, editorReduce, initEditor, resolveInsertParent, useEditor } from './chunk-IOMIYI45.js';
|
|
3
|
+
import { isBinding } from './chunk-SJYKJ6SG.js';
|
|
4
|
+
export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, hasNodeMap, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds } from './chunk-SJYKJ6SG.js';
|
|
5
5
|
export { fractionalKey, fractionalKey as keyBetween } from '@particle-academy/fancy-doc-commons';
|
|
6
6
|
|
|
7
7
|
// src/document/bindings.ts
|
package/dist/react.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var react = require('react');
|
|
3
4
|
var fancyDocCommons = require('@particle-academy/fancy-doc-commons');
|
|
4
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
var react = require('react');
|
|
6
6
|
|
|
7
|
-
// src/
|
|
7
|
+
// src/react/RenderNode.tsx
|
|
8
8
|
|
|
9
9
|
// src/document/types.ts
|
|
10
10
|
function isBinding(v) {
|
|
@@ -31,6 +31,15 @@ function emptyDoc(id, slug = "/") {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// src/document/own.ts
|
|
35
|
+
var has = Object.prototype.hasOwnProperty;
|
|
36
|
+
function own(map, key) {
|
|
37
|
+
return map != null && has.call(map, key) ? map[key] : void 0;
|
|
38
|
+
}
|
|
39
|
+
function setOwn(map, key, value) {
|
|
40
|
+
Object.defineProperty(map, key, { value, writable: true, enumerable: true, configurable: true });
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
// src/document/reduce.ts
|
|
35
44
|
function childrenOf(doc, parent) {
|
|
36
45
|
return fancyDocCommons.childrenOf(doc, parent);
|
|
@@ -47,6 +56,48 @@ function resolveValue(v, data) {
|
|
|
47
56
|
if (isBinding(v)) return getPath(data, v.$bind);
|
|
48
57
|
return v;
|
|
49
58
|
}
|
|
59
|
+
var LANDMARK_TAGS = ["section", "header", "nav", "main", "footer", "article", "aside", "div"];
|
|
60
|
+
var LANDMARKS = new Set(LANDMARK_TAGS);
|
|
61
|
+
var CONTAINERS = /* @__PURE__ */ new Set(["stack", "grid", "frame", "shape", "card"]);
|
|
62
|
+
var SAFE_SCHEMES = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
|
|
63
|
+
function safeHref(raw) {
|
|
64
|
+
const href = raw.trim();
|
|
65
|
+
if (!href) return null;
|
|
66
|
+
const probe = href.replace(/[\u0000- \u007f]+/g, "");
|
|
67
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(probe);
|
|
68
|
+
if (scheme && !SAFE_SCHEMES.has(scheme[1].toLowerCase())) return null;
|
|
69
|
+
return href;
|
|
70
|
+
}
|
|
71
|
+
var ANCHOR_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
72
|
+
function anchorFor(node, text) {
|
|
73
|
+
const anchor = text(node.props.anchor);
|
|
74
|
+
return ANCHOR_PATTERN.test(anchor) ? anchor : null;
|
|
75
|
+
}
|
|
76
|
+
function elementFor(node, text) {
|
|
77
|
+
const as = text(node.props.as);
|
|
78
|
+
switch (node.type) {
|
|
79
|
+
case "heading": {
|
|
80
|
+
const level = Number(text(node.props.level) || 2);
|
|
81
|
+
return { tag: Number.isInteger(level) && level >= 1 && level <= 6 ? `h${level}` : "h2" };
|
|
82
|
+
}
|
|
83
|
+
case "text":
|
|
84
|
+
return { tag: "p" };
|
|
85
|
+
case "section":
|
|
86
|
+
return { tag: LANDMARKS.has(as) ? as : "section" };
|
|
87
|
+
case "list":
|
|
88
|
+
return { tag: text(node.props.ordered) === "true" ? "ol" : "ul" };
|
|
89
|
+
case "button":
|
|
90
|
+
case "link": {
|
|
91
|
+
const href = safeHref(text(node.props.href));
|
|
92
|
+
if (href === null) return { tag: node.type === "link" ? "span" : "div" };
|
|
93
|
+
const attrs = { href };
|
|
94
|
+
if (/^https?:\/\//i.test(href)) attrs.rel = "noopener noreferrer";
|
|
95
|
+
return { tag: "a", attrs };
|
|
96
|
+
}
|
|
97
|
+
default:
|
|
98
|
+
return { tag: CONTAINERS.has(node.type) && LANDMARKS.has(as) ? as : "div" };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
50
101
|
var defaultRegistry = {
|
|
51
102
|
section: ({ children }) => children,
|
|
52
103
|
stack: ({ children }) => children,
|
|
@@ -59,7 +110,12 @@ var defaultRegistry = {
|
|
|
59
110
|
// Rich text — inline-formatted HTML (gradient spans, links, <code>, …) that
|
|
60
111
|
// plain `text` can't express. The author owns the markup (it's their content).
|
|
61
112
|
richtext: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: text(node.props.html) } }),
|
|
62
|
-
|
|
113
|
+
// The [data-cms] element is already the <a> (see elementFor), so a link renders its label only.
|
|
114
|
+
link: ({ node, text }) => text(node.props.content) || "link",
|
|
115
|
+
list: ({ node, resolve }) => {
|
|
116
|
+
const items = resolve(node.props.items);
|
|
117
|
+
return Array.isArray(items) ? items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: item === null || item === void 0 ? "" : String(item) }, i)) : null;
|
|
118
|
+
},
|
|
63
119
|
divider: () => /* @__PURE__ */ jsxRuntime.jsx("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: 0 } }),
|
|
64
120
|
callout: ({ node, text }) => {
|
|
65
121
|
const tone = { info: "#3b82f6", success: "#10b981", warning: "#f59e0b", danger: "#ef4444" }[text(node.props.variant)] ?? "#3b82f6";
|
|
@@ -71,15 +127,20 @@ var defaultRegistry = {
|
|
|
71
127
|
const variant = text(node.props.variant) || "primary";
|
|
72
128
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cms-button": variant, style: buttonStyle(variant), children: label });
|
|
73
129
|
},
|
|
74
|
-
image: ({ node, text }) =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
130
|
+
image: ({ node, text }) => {
|
|
131
|
+
const fit = text(node.props.fit);
|
|
132
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
133
|
+
"img",
|
|
134
|
+
{
|
|
135
|
+
src: text(node.props.src),
|
|
136
|
+
alt: text(node.props.alt),
|
|
137
|
+
loading: text(node.props.loading) === "eager" ? "eager" : "lazy",
|
|
138
|
+
style: { width: "100%", height: "100%", objectFit: IMAGE_FITS.has(fit) ? fit : "cover", display: "block" }
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
82
142
|
};
|
|
143
|
+
var IMAGE_FITS = /* @__PURE__ */ new Set(["cover", "contain", "fill", "none", "scale-down"]);
|
|
83
144
|
function buttonStyle(variant) {
|
|
84
145
|
const base = {
|
|
85
146
|
display: "inline-flex",
|
|
@@ -98,7 +159,7 @@ function buttonStyle(variant) {
|
|
|
98
159
|
return { ...base, background: "#7c3aed", color: "#fff", border: "1px solid #7c3aed" };
|
|
99
160
|
}
|
|
100
161
|
function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
101
|
-
const node = doc.nodes
|
|
162
|
+
const node = own(doc.nodes, id);
|
|
102
163
|
if (!node) return null;
|
|
103
164
|
if (node.type === "repeater") {
|
|
104
165
|
const arr = resolveValue(node.props.items, data);
|
|
@@ -114,7 +175,19 @@ function RenderNode({ doc, id, registry = defaultRegistry, data }) {
|
|
|
114
175
|
};
|
|
115
176
|
const renderer = registry[node.type];
|
|
116
177
|
const inner = renderer ? renderer({ node, doc, children: kids, data, resolve, text }) : node.island ? null : kids;
|
|
117
|
-
|
|
178
|
+
const { tag, attrs } = elementFor(node, text);
|
|
179
|
+
const anchor = anchorFor(node, text);
|
|
180
|
+
return react.createElement(
|
|
181
|
+
tag,
|
|
182
|
+
{
|
|
183
|
+
"data-cms": node.id,
|
|
184
|
+
"data-cms-island": node.island ? node.type : void 0,
|
|
185
|
+
className: node.className,
|
|
186
|
+
...anchor ? { id: anchor } : {},
|
|
187
|
+
...attrs
|
|
188
|
+
},
|
|
189
|
+
inner
|
|
190
|
+
);
|
|
118
191
|
}
|
|
119
192
|
function normalizeDoc(input) {
|
|
120
193
|
if (hasNodeMap(input)) return input;
|
|
@@ -132,7 +205,7 @@ function migrateDocVerbose(input) {
|
|
|
132
205
|
const ordered = [];
|
|
133
206
|
const seen = /* @__PURE__ */ new Set();
|
|
134
207
|
for (const id of sections) {
|
|
135
|
-
if (!normalized.nodes
|
|
208
|
+
if (!own(normalized.nodes, id)) {
|
|
136
209
|
danglingIds.push(id);
|
|
137
210
|
continue;
|
|
138
211
|
}
|
|
@@ -146,7 +219,7 @@ function migrateDocVerbose(input) {
|
|
|
146
219
|
let prev = null;
|
|
147
220
|
for (const id of finalOrder) {
|
|
148
221
|
const key = fancyDocCommons.fractionalKey(prev, null);
|
|
149
|
-
nodes
|
|
222
|
+
setOwn(nodes, id, { ...own(nodes, id), order: key });
|
|
150
223
|
prev = key;
|
|
151
224
|
}
|
|
152
225
|
const { sections: _dropped, ...rest } = legacy;
|
|
@@ -162,15 +235,36 @@ function migrateDoc(input) {
|
|
|
162
235
|
}
|
|
163
236
|
|
|
164
237
|
// src/render/css.ts
|
|
165
|
-
|
|
238
|
+
function cssString(value) {
|
|
239
|
+
let out = "";
|
|
240
|
+
for (const ch of value) {
|
|
241
|
+
const code = ch.codePointAt(0);
|
|
242
|
+
if (ch === "\\" || ch === '"') out += `\\${ch}`;
|
|
243
|
+
else if (code < 32 || code === 127 || ch === "<") out += `\\${code.toString(16)} `;
|
|
244
|
+
else out += ch;
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
var selectorFor = (id) => `[data-cms="${cssString(id)}"]`;
|
|
249
|
+
var UNITS = /* @__PURE__ */ new Set(["px", "%", "vw", "vh", "rem", "fr"]);
|
|
166
250
|
function lengthToCss(len) {
|
|
167
|
-
|
|
251
|
+
if (typeof len !== "object" || len === null) return null;
|
|
252
|
+
const { value, unit } = len;
|
|
253
|
+
if (typeof value !== "number" || !Number.isFinite(value) || typeof unit !== "string" || !UNITS.has(unit)) return null;
|
|
254
|
+
return `${value}${unit}`;
|
|
168
255
|
}
|
|
169
256
|
function sizeToCss(size) {
|
|
170
257
|
if (size === "fill") return "100%";
|
|
171
258
|
if (size === "hug") return "auto";
|
|
172
259
|
return lengthToCss(size);
|
|
173
260
|
}
|
|
261
|
+
function numberToCss(value) {
|
|
262
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : null;
|
|
263
|
+
}
|
|
264
|
+
function putLen(d, props, len) {
|
|
265
|
+
const css = lengthToCss(len);
|
|
266
|
+
if (css !== null) for (const p of props) d[p] = css;
|
|
267
|
+
}
|
|
174
268
|
var ALIGN = {
|
|
175
269
|
start: "flex-start",
|
|
176
270
|
center: "center",
|
|
@@ -184,51 +278,150 @@ var JUSTIFY = {
|
|
|
184
278
|
between: "space-between",
|
|
185
279
|
around: "space-around"
|
|
186
280
|
};
|
|
281
|
+
function safeCssValue(value) {
|
|
282
|
+
if (/[{}<]/.test(value)) return null;
|
|
283
|
+
let depth = 0;
|
|
284
|
+
let quote = null;
|
|
285
|
+
for (const ch of value) {
|
|
286
|
+
if (quote) {
|
|
287
|
+
if (ch === quote) quote = null;
|
|
288
|
+
} else if (ch === '"' || ch === "'") {
|
|
289
|
+
quote = ch;
|
|
290
|
+
} else if (ch === "(") {
|
|
291
|
+
depth++;
|
|
292
|
+
} else if (ch === ")") {
|
|
293
|
+
depth = Math.max(0, depth - 1);
|
|
294
|
+
} else if (ch === ";" && depth === 0) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return value;
|
|
299
|
+
}
|
|
300
|
+
function put(d, prop, value) {
|
|
301
|
+
if (value === void 0) return;
|
|
302
|
+
const safe = safeCssValue(value);
|
|
303
|
+
if (safe !== null) d[prop] = safe;
|
|
304
|
+
}
|
|
305
|
+
var OVERFLOW = /* @__PURE__ */ new Set(["visible", "hidden", "auto"]);
|
|
306
|
+
var TEXT_TRANSFORM = /* @__PURE__ */ new Set(["none", "uppercase", "lowercase", "capitalize"]);
|
|
307
|
+
var BACKGROUND_SIZE = /* @__PURE__ */ new Set(["cover", "contain", "auto"]);
|
|
308
|
+
var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right", "justify"]);
|
|
309
|
+
var DIRECTIONS = /* @__PURE__ */ new Set(["row", "column"]);
|
|
310
|
+
function keyword(map, value) {
|
|
311
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(map, value) ? map[value] : null;
|
|
312
|
+
}
|
|
313
|
+
function inSet(set, value) {
|
|
314
|
+
return typeof value === "string" && set.has(value) ? value : null;
|
|
315
|
+
}
|
|
187
316
|
function styleDecls(style) {
|
|
188
317
|
const d = {};
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (style.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (style.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (style.
|
|
205
|
-
|
|
206
|
-
if (
|
|
207
|
-
|
|
318
|
+
putLen(d, ["padding"], style.padding);
|
|
319
|
+
putLen(d, ["padding-left", "padding-right"], style.paddingX);
|
|
320
|
+
putLen(d, ["padding-top", "padding-bottom"], style.paddingY);
|
|
321
|
+
putLen(d, ["margin"], style.margin);
|
|
322
|
+
if (style.marginX === "auto") d["margin-left"] = d["margin-right"] = "auto";
|
|
323
|
+
else putLen(d, ["margin-left", "margin-right"], style.marginX);
|
|
324
|
+
putLen(d, ["margin-top", "margin-bottom"], style.marginY);
|
|
325
|
+
putLen(d, ["border-radius"], style.radius);
|
|
326
|
+
putLen(d, ["max-width"], style.maxWidth);
|
|
327
|
+
putLen(d, ["min-height"], style.minHeight);
|
|
328
|
+
put(d, "aspect-ratio", typeof style.aspectRatio === "string" ? style.aspectRatio : void 0);
|
|
329
|
+
if (style.sticky === true) {
|
|
330
|
+
d["position"] = "sticky";
|
|
331
|
+
d["top"] = "0";
|
|
332
|
+
}
|
|
333
|
+
if (typeof style.zIndex === "number" && Number.isFinite(style.zIndex)) d["z-index"] = String(Math.trunc(style.zIndex));
|
|
334
|
+
const overflow = inSet(OVERFLOW, style.overflow);
|
|
335
|
+
if (overflow) d["overflow"] = overflow;
|
|
336
|
+
put(d, "background", typeof style.background === "string" ? style.background : void 0);
|
|
337
|
+
const backgroundSize = inSet(BACKGROUND_SIZE, style.backgroundSize);
|
|
338
|
+
if (backgroundSize) d["background-size"] = backgroundSize;
|
|
339
|
+
put(d, "background-position", typeof style.backgroundPosition === "string" ? style.backgroundPosition : void 0);
|
|
340
|
+
put(d, "color", typeof style.color === "string" ? style.color : void 0);
|
|
341
|
+
const opacity = numberToCss(style.opacity);
|
|
342
|
+
if (opacity !== null) d["opacity"] = opacity;
|
|
343
|
+
put(d, "font-family", typeof style.fontFamily === "string" ? style.fontFamily : void 0);
|
|
344
|
+
putLen(d, ["font-size"], style.fontSize);
|
|
345
|
+
const fontWeight = numberToCss(style.fontWeight);
|
|
346
|
+
if (fontWeight !== null) d["font-weight"] = fontWeight;
|
|
347
|
+
const lineHeight = numberToCss(style.lineHeight);
|
|
348
|
+
if (lineHeight !== null) d["line-height"] = lineHeight;
|
|
349
|
+
const textAlign = inSet(TEXT_ALIGN, style.textAlign);
|
|
350
|
+
if (textAlign) d["text-align"] = textAlign;
|
|
351
|
+
putLen(d, ["letter-spacing"], style.letterSpacing);
|
|
352
|
+
const textTransform = inSet(TEXT_TRANSFORM, style.textTransform);
|
|
353
|
+
if (textTransform) d["text-transform"] = textTransform;
|
|
354
|
+
put(d, "border", typeof style.border === "string" ? style.border : void 0);
|
|
355
|
+
put(d, "box-shadow", typeof style.boxShadow === "string" ? style.boxShadow : void 0);
|
|
356
|
+
put(d, "transform", typeof style.transform === "string" ? style.transform : void 0);
|
|
357
|
+
put(d, "filter", typeof style.filter === "string" ? style.filter : void 0);
|
|
358
|
+
putLen(d, ["gap"], style.gap);
|
|
359
|
+
const align = keyword(ALIGN, style.align);
|
|
360
|
+
if (align) d["align-items"] = align;
|
|
361
|
+
const justify = keyword(JUSTIFY, style.justify);
|
|
362
|
+
if (justify) d["justify-content"] = justify;
|
|
208
363
|
return d;
|
|
209
364
|
}
|
|
210
|
-
function
|
|
365
|
+
function shownDisplay(node) {
|
|
366
|
+
if (node.layout === "stack") return "flex";
|
|
367
|
+
if (node.layout === "grid") return "grid";
|
|
368
|
+
return "block";
|
|
369
|
+
}
|
|
370
|
+
function gridColumns(style) {
|
|
371
|
+
const min = lengthToCss(style.columnMin);
|
|
372
|
+
if (min !== null) return `repeat(auto-fit, minmax(min(${min}, 100%), 1fr))`;
|
|
373
|
+
if (typeof style.columns === "number" && Number.isFinite(style.columns)) return `repeat(${Math.max(1, Math.trunc(style.columns))}, 1fr)`;
|
|
374
|
+
return void 0;
|
|
375
|
+
}
|
|
376
|
+
function containerDecls(node, style, isBase) {
|
|
211
377
|
const d = {};
|
|
212
378
|
if (node.layout === "stack") {
|
|
213
|
-
d["display"] = "flex";
|
|
214
|
-
|
|
379
|
+
if (isBase) d["display"] = "flex";
|
|
380
|
+
const direction = inSet(DIRECTIONS, style.direction);
|
|
381
|
+
if (isBase || direction) d["flex-direction"] = direction ?? "column";
|
|
382
|
+
if (style.wrap !== void 0) d["flex-wrap"] = style.wrap ? "wrap" : "nowrap";
|
|
215
383
|
} else if (node.layout === "grid") {
|
|
216
|
-
d["display"] = "grid";
|
|
217
|
-
|
|
218
|
-
|
|
384
|
+
if (isBase) d["display"] = "grid";
|
|
385
|
+
const cols = gridColumns(style);
|
|
386
|
+
if (isBase || cols !== void 0) d["grid-template-columns"] = cols ?? "repeat(1, 1fr)";
|
|
387
|
+
} else if (node.layout === "free" && isBase) {
|
|
219
388
|
d["position"] = "relative";
|
|
220
389
|
}
|
|
221
390
|
return d;
|
|
222
391
|
}
|
|
392
|
+
function visibilityDecls(node, style, isBase) {
|
|
393
|
+
if (style.hidden === true) return { display: "none" };
|
|
394
|
+
if (style.hidden === false && !isBase) return { display: shownDisplay(node) };
|
|
395
|
+
return {};
|
|
396
|
+
}
|
|
397
|
+
function themeDecls(theme) {
|
|
398
|
+
const d = {};
|
|
399
|
+
const walk = (value, path) => {
|
|
400
|
+
if (typeof value === "string" || typeof value === "number" && Number.isFinite(value)) {
|
|
401
|
+
const key = path.map((p) => p.toLowerCase().replace(/[^a-z0-9-]/g, "")).filter(Boolean).join("-");
|
|
402
|
+
if (key) put(d, `--cms-${key}`, String(value));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
406
|
+
for (const [k, v] of Object.entries(value)) walk(v, [...path, k]);
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
if (typeof theme === "object" && theme !== null && !Array.isArray(theme)) {
|
|
410
|
+
for (const [k, v] of Object.entries(theme)) {
|
|
411
|
+
if (k !== "name") walk(v, [k]);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return d;
|
|
415
|
+
}
|
|
223
416
|
function constraintDecls(c, parentFree) {
|
|
224
417
|
const d = {};
|
|
225
418
|
const transforms = [];
|
|
226
419
|
if (parentFree) {
|
|
227
420
|
d["position"] = "absolute";
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
421
|
+
putLen(d, ["left"], c.left);
|
|
422
|
+
putLen(d, ["right"], c.right);
|
|
423
|
+
putLen(d, ["top"], c.top);
|
|
424
|
+
putLen(d, ["bottom"], c.bottom);
|
|
232
425
|
if (c.centerX) {
|
|
233
426
|
d["left"] = "50%";
|
|
234
427
|
transforms.push("translateX(-50%)");
|
|
@@ -239,13 +432,15 @@ function constraintDecls(c, parentFree) {
|
|
|
239
432
|
}
|
|
240
433
|
if (transforms.length) d["transform"] = transforms.join(" ");
|
|
241
434
|
}
|
|
242
|
-
|
|
243
|
-
if (
|
|
435
|
+
const width = sizeToCss(c.width);
|
|
436
|
+
if (width !== null) d["width"] = width;
|
|
437
|
+
const height = sizeToCss(c.height);
|
|
438
|
+
if (height !== null) d["height"] = height;
|
|
244
439
|
return d;
|
|
245
440
|
}
|
|
246
441
|
function isParentFree(doc, node) {
|
|
247
442
|
if (node.parent === null) return false;
|
|
248
|
-
const parent = doc.nodes
|
|
443
|
+
const parent = own(doc.nodes, node.parent);
|
|
249
444
|
return !parent || parent.layout === void 0 || parent.layout === "free";
|
|
250
445
|
}
|
|
251
446
|
function serializeRule(selector, decls, indent) {
|
|
@@ -260,14 +455,17 @@ function emitDocCss(doc) {
|
|
|
260
455
|
if (!hasNodeMap(doc)) return "";
|
|
261
456
|
const breakpointPx = DEFAULT_BREAKPOINTS;
|
|
262
457
|
const blocks = [];
|
|
458
|
+
const themeRule = serializeRule(":root", themeDecls(doc.theme), "");
|
|
459
|
+
if (themeRule) blocks.push(themeRule);
|
|
263
460
|
for (const id of Object.keys(doc.nodes).sort()) {
|
|
264
461
|
const node = doc.nodes[id];
|
|
265
462
|
const selector = selectorFor(id);
|
|
266
463
|
const parentFree = isParentFree(doc, node);
|
|
267
464
|
const base = {
|
|
268
|
-
...
|
|
465
|
+
...containerDecls(node, node.style.base, true),
|
|
269
466
|
...node.constraints ? constraintDecls(node.constraints.base, parentFree) : {},
|
|
270
|
-
...styleDecls(node.style.base)
|
|
467
|
+
...styleDecls(node.style.base),
|
|
468
|
+
...visibilityDecls(node, node.style.base, true)
|
|
271
469
|
};
|
|
272
470
|
const baseRule = serializeRule(selector, base, "");
|
|
273
471
|
if (baseRule) blocks.push(baseRule);
|
|
@@ -275,9 +473,12 @@ function emitDocCss(doc) {
|
|
|
275
473
|
if (bp === "base") continue;
|
|
276
474
|
const px = breakpointPx[bp];
|
|
277
475
|
if (px === void 0) continue;
|
|
476
|
+
const bpStyle = node.style[bp];
|
|
278
477
|
const decls = {
|
|
478
|
+
...bpStyle ? containerDecls(node, bpStyle, false) : {},
|
|
279
479
|
...node.constraints?.[bp] ? constraintDecls(node.constraints[bp], parentFree) : {},
|
|
280
|
-
...
|
|
480
|
+
...bpStyle ? styleDecls(bpStyle) : {},
|
|
481
|
+
...bpStyle ? visibilityDecls(node, bpStyle, false) : {}
|
|
281
482
|
};
|
|
282
483
|
const inner = serializeRule(selector, decls, " ");
|
|
283
484
|
if (inner) blocks.push(`@media (min-width: ${px}px) {
|