@nextlyhq/plugin-page-builder 0.0.2-alpha.31
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/README.md +240 -0
- package/dist/admin/index.d.ts +56 -0
- package/dist/admin/index.js +2463 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/chunk-7VN7UNLK.js +45 -0
- package/dist/chunk-7VN7UNLK.js.map +1 -0
- package/dist/chunk-ABMSYCSD.js +355 -0
- package/dist/chunk-ABMSYCSD.js.map +1 -0
- package/dist/chunk-E4G7NNXW.js +21 -0
- package/dist/chunk-E4G7NNXW.js.map +1 -0
- package/dist/chunk-EGU6QGUC.js +119 -0
- package/dist/chunk-EGU6QGUC.js.map +1 -0
- package/dist/chunk-R7YHOSL2.js +483 -0
- package/dist/chunk-R7YHOSL2.js.map +1 -0
- package/dist/index.d.ts +196 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/render/ErrorBoundary.d.ts +23 -0
- package/dist/render/ErrorBoundary.js +8 -0
- package/dist/render/ErrorBoundary.js.map +1 -0
- package/dist/render/index.d.ts +151 -0
- package/dist/render/index.js +64 -0
- package/dist/render/index.js.map +1 -0
- package/dist/style-compiler-hnWIDfko.d.ts +212 -0
- package/dist/styles/editor.css +412 -0
- package/package.json +109 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_SLOT,
|
|
3
|
+
defineBlock,
|
|
4
|
+
nodeClass,
|
|
5
|
+
resolveBindings
|
|
6
|
+
} from "./chunk-ABMSYCSD.js";
|
|
7
|
+
import {
|
|
8
|
+
BlockErrorBoundary
|
|
9
|
+
} from "./chunk-E4G7NNXW.js";
|
|
10
|
+
|
|
11
|
+
// src/render/blocks/paragraph.tsx
|
|
12
|
+
import { jsx } from "react/jsx-runtime";
|
|
13
|
+
var paragraph = defineBlock({
|
|
14
|
+
type: "core/paragraph",
|
|
15
|
+
version: 1,
|
|
16
|
+
label: "Paragraph",
|
|
17
|
+
icon: "Type",
|
|
18
|
+
category: "basic",
|
|
19
|
+
defaultProps: { text: "New paragraph" },
|
|
20
|
+
contentFields: [
|
|
21
|
+
{ name: "text", type: "textarea", label: "Text", bindable: true }
|
|
22
|
+
],
|
|
23
|
+
styleControls: [
|
|
24
|
+
{ control: "color", styleKey: "color", label: "Text color" },
|
|
25
|
+
{ control: "dimension", styleKey: "fontSize", label: "Font size" },
|
|
26
|
+
{ control: "align", styleKey: "textAlign", label: "Align" },
|
|
27
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
28
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
29
|
+
],
|
|
30
|
+
render: ({ props, className }) => /* @__PURE__ */ jsx("p", { className, children: String(props.text ?? "") })
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// src/render/blocks/heading.tsx
|
|
34
|
+
import { createElement } from "react";
|
|
35
|
+
var LEVELS = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
36
|
+
var heading = defineBlock({
|
|
37
|
+
type: "core/heading",
|
|
38
|
+
version: 1,
|
|
39
|
+
label: "Heading",
|
|
40
|
+
icon: "Heading",
|
|
41
|
+
category: "basic",
|
|
42
|
+
defaultProps: { text: "New heading", level: "h2" },
|
|
43
|
+
contentFields: [
|
|
44
|
+
{ name: "text", type: "text", label: "Text", bindable: true },
|
|
45
|
+
{
|
|
46
|
+
name: "level",
|
|
47
|
+
type: "select",
|
|
48
|
+
label: "Level",
|
|
49
|
+
options: LEVELS.map((l) => ({ value: l, label: l.toUpperCase() }))
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
styleControls: [
|
|
53
|
+
{ control: "color", styleKey: "color", label: "Text color" },
|
|
54
|
+
{ control: "dimension", styleKey: "fontSize", label: "Font size" },
|
|
55
|
+
{ control: "align", styleKey: "textAlign", label: "Align" },
|
|
56
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
57
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
58
|
+
],
|
|
59
|
+
render: ({ props, className }) => {
|
|
60
|
+
const level = LEVELS.includes(String(props.level)) ? String(props.level) : "h2";
|
|
61
|
+
return createElement(level, { className }, String(props.text ?? ""));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// src/render/blocks/util.ts
|
|
66
|
+
function safeUrl(url) {
|
|
67
|
+
if (typeof url !== "string") return void 0;
|
|
68
|
+
const trimmed = url.trim();
|
|
69
|
+
if (!trimmed) return void 0;
|
|
70
|
+
const scheme = trimmed.replace(/[\u0000-\u0020\u007f]+/g, "").toLowerCase();
|
|
71
|
+
if (/^(javascript|vbscript|data):/.test(scheme)) return void 0;
|
|
72
|
+
return trimmed;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/render/blocks/image.tsx
|
|
76
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
77
|
+
var image = defineBlock({
|
|
78
|
+
type: "core/image",
|
|
79
|
+
version: 1,
|
|
80
|
+
label: "Image",
|
|
81
|
+
icon: "Image",
|
|
82
|
+
category: "media",
|
|
83
|
+
defaultProps: { url: "", alt: "" },
|
|
84
|
+
contentFields: [
|
|
85
|
+
{ name: "media", type: "media", label: "Image", bindable: true }
|
|
86
|
+
],
|
|
87
|
+
styleControls: [
|
|
88
|
+
{ control: "dimension", styleKey: "width", label: "Width" },
|
|
89
|
+
{ control: "dimension", styleKey: "borderRadius", label: "Radius" },
|
|
90
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
91
|
+
],
|
|
92
|
+
render: ({ props, className }) => {
|
|
93
|
+
const raw = props.media;
|
|
94
|
+
const media = typeof raw === "string" ? { url: raw } : raw ?? {};
|
|
95
|
+
const src = safeUrl(media.url ?? props.url);
|
|
96
|
+
if (!src) return null;
|
|
97
|
+
const alt = media.alt ?? props.alt;
|
|
98
|
+
const width = media.width ?? props.width;
|
|
99
|
+
const height = media.height ?? props.height;
|
|
100
|
+
return /* @__PURE__ */ jsx2(
|
|
101
|
+
"img",
|
|
102
|
+
{
|
|
103
|
+
className,
|
|
104
|
+
src,
|
|
105
|
+
alt: typeof alt === "string" ? alt : "",
|
|
106
|
+
width: typeof width === "number" ? width : void 0,
|
|
107
|
+
height: typeof height === "number" ? height : void 0,
|
|
108
|
+
loading: "lazy"
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// src/render/blocks/button.tsx
|
|
115
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
116
|
+
var button = defineBlock({
|
|
117
|
+
type: "core/button",
|
|
118
|
+
version: 1,
|
|
119
|
+
label: "Button",
|
|
120
|
+
icon: "MousePointerClick",
|
|
121
|
+
category: "basic",
|
|
122
|
+
defaultProps: { text: "Click me", link: { href: "", target: "" } },
|
|
123
|
+
contentFields: [
|
|
124
|
+
{ name: "text", type: "text", label: "Label", bindable: true },
|
|
125
|
+
{ name: "link", type: "link", label: "Link" }
|
|
126
|
+
],
|
|
127
|
+
styleControls: [
|
|
128
|
+
{ control: "color", styleKey: "color", label: "Text color" },
|
|
129
|
+
{ control: "color", styleKey: "backgroundColor", label: "Background" },
|
|
130
|
+
{ control: "dimension", styleKey: "borderRadius", label: "Radius" },
|
|
131
|
+
{ control: "align", styleKey: "textAlign", label: "Align" },
|
|
132
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
133
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
134
|
+
],
|
|
135
|
+
render: ({ props, className }) => {
|
|
136
|
+
const link = props.link ?? {};
|
|
137
|
+
const href = safeUrl(link.href);
|
|
138
|
+
const text = String(props.text ?? "Button");
|
|
139
|
+
if (!href) {
|
|
140
|
+
return /* @__PURE__ */ jsx3("button", { className, type: "button", children: text });
|
|
141
|
+
}
|
|
142
|
+
const target = link.target || void 0;
|
|
143
|
+
return /* @__PURE__ */ jsx3(
|
|
144
|
+
"a",
|
|
145
|
+
{
|
|
146
|
+
className,
|
|
147
|
+
href,
|
|
148
|
+
target,
|
|
149
|
+
rel: target === "_blank" ? "noopener noreferrer" : void 0,
|
|
150
|
+
children: text
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// src/render/blocks/video.tsx
|
|
157
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
158
|
+
function embedUrl(provider, id) {
|
|
159
|
+
const safeId = encodeURIComponent(id);
|
|
160
|
+
if (provider === "youtube") return `https://www.youtube.com/embed/${safeId}`;
|
|
161
|
+
if (provider === "vimeo") return `https://player.vimeo.com/video/${safeId}`;
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
var video = defineBlock({
|
|
165
|
+
type: "core/video",
|
|
166
|
+
version: 1,
|
|
167
|
+
label: "Video",
|
|
168
|
+
icon: "Video",
|
|
169
|
+
category: "media",
|
|
170
|
+
defaultProps: { provider: "youtube", videoId: "" },
|
|
171
|
+
contentFields: [
|
|
172
|
+
{
|
|
173
|
+
name: "provider",
|
|
174
|
+
type: "select",
|
|
175
|
+
label: "Provider",
|
|
176
|
+
options: [
|
|
177
|
+
{ value: "youtube", label: "YouTube" },
|
|
178
|
+
{ value: "vimeo", label: "Vimeo" }
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "videoId",
|
|
183
|
+
type: "text",
|
|
184
|
+
label: "Video ID",
|
|
185
|
+
placeholder: "e.g. dQw4w9WgXcQ"
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
styleControls: [
|
|
189
|
+
{ control: "dimension", styleKey: "maxWidth", label: "Max width" },
|
|
190
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
191
|
+
],
|
|
192
|
+
render: ({ props, className }) => {
|
|
193
|
+
const provider = String(props.provider ?? "");
|
|
194
|
+
const id = typeof props.videoId === "string" ? props.videoId.trim() : "";
|
|
195
|
+
const src = id ? embedUrl(provider, id) : null;
|
|
196
|
+
if (!src) return null;
|
|
197
|
+
return /* @__PURE__ */ jsx4("div", { className, children: /* @__PURE__ */ jsx4(
|
|
198
|
+
"iframe",
|
|
199
|
+
{
|
|
200
|
+
src,
|
|
201
|
+
title: "Embedded video",
|
|
202
|
+
allowFullScreen: true,
|
|
203
|
+
style: { border: 0, width: "100%", aspectRatio: "16 / 9" }
|
|
204
|
+
}
|
|
205
|
+
) });
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// src/render/blocks/container.tsx
|
|
210
|
+
import { createElement as createElement2 } from "react";
|
|
211
|
+
var TAGS = ["section", "div", "article", "header", "footer", "aside"];
|
|
212
|
+
var container = defineBlock({
|
|
213
|
+
type: "core/container",
|
|
214
|
+
version: 1,
|
|
215
|
+
label: "Container",
|
|
216
|
+
icon: "Square",
|
|
217
|
+
category: "layout",
|
|
218
|
+
isContainer: true,
|
|
219
|
+
slots: [{ name: "default" }],
|
|
220
|
+
defaultProps: { as: "section" },
|
|
221
|
+
contentFields: [
|
|
222
|
+
{
|
|
223
|
+
name: "as",
|
|
224
|
+
type: "select",
|
|
225
|
+
label: "HTML tag",
|
|
226
|
+
options: TAGS.map((t) => ({ value: t, label: t }))
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
styleControls: [
|
|
230
|
+
{ control: "color", styleKey: "backgroundColor", label: "Background" },
|
|
231
|
+
{ control: "dimension", styleKey: "maxWidth", label: "Max width" },
|
|
232
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
233
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" },
|
|
234
|
+
{ control: "dimension", styleKey: "borderRadius", label: "Radius" }
|
|
235
|
+
],
|
|
236
|
+
render: ({ props, slots, className }) => {
|
|
237
|
+
const tag = TAGS.includes(String(props.as)) ? String(props.as) : "section";
|
|
238
|
+
return createElement2(tag, { className }, slots.default);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// src/render/blocks/grid.tsx
|
|
243
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
244
|
+
var grid = defineBlock({
|
|
245
|
+
type: "core/grid",
|
|
246
|
+
version: 1,
|
|
247
|
+
label: "Grid",
|
|
248
|
+
icon: "LayoutGrid",
|
|
249
|
+
category: "layout",
|
|
250
|
+
isContainer: true,
|
|
251
|
+
slots: [{ name: "default" }],
|
|
252
|
+
defaultProps: { columns: 2, gap: "16px" },
|
|
253
|
+
contentFields: [
|
|
254
|
+
{ name: "columns", type: "number", label: "Columns" },
|
|
255
|
+
{ name: "gap", type: "text", label: "Gap", placeholder: "16px" }
|
|
256
|
+
],
|
|
257
|
+
styleControls: [
|
|
258
|
+
{ control: "color", styleKey: "backgroundColor", label: "Background" },
|
|
259
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
260
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
261
|
+
],
|
|
262
|
+
render: ({ props, slots, className }) => {
|
|
263
|
+
const columns = typeof props.columns === "number" && props.columns > 0 ? Math.min(props.columns, 12) : 2;
|
|
264
|
+
const gap = typeof props.gap === "string" ? props.gap : "16px";
|
|
265
|
+
return /* @__PURE__ */ jsx5(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
className,
|
|
269
|
+
style: {
|
|
270
|
+
display: "grid",
|
|
271
|
+
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
|
|
272
|
+
gap
|
|
273
|
+
},
|
|
274
|
+
children: slots.default
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// src/render/query/grid.ts
|
|
281
|
+
function loopGridStyle(props) {
|
|
282
|
+
const raw = typeof props.columns === "number" ? props.columns : 1;
|
|
283
|
+
const columns = raw > 1 ? Math.min(Math.floor(raw), 12) : 0;
|
|
284
|
+
if (!columns) return void 0;
|
|
285
|
+
const gap = typeof props.gap === "string" ? props.gap : "16px";
|
|
286
|
+
return {
|
|
287
|
+
display: "grid",
|
|
288
|
+
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
|
|
289
|
+
gap
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/render/blocks/queryLoop.tsx
|
|
294
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
295
|
+
var queryLoop = defineBlock({
|
|
296
|
+
type: "core/query-loop",
|
|
297
|
+
version: 1,
|
|
298
|
+
label: "Query Loop",
|
|
299
|
+
icon: "Repeat",
|
|
300
|
+
category: "dynamic",
|
|
301
|
+
isContainer: true,
|
|
302
|
+
slots: [{ name: "default" }],
|
|
303
|
+
defaultProps: {
|
|
304
|
+
collection: "",
|
|
305
|
+
sort: "",
|
|
306
|
+
limit: 10,
|
|
307
|
+
columns: 1,
|
|
308
|
+
gap: "16px"
|
|
309
|
+
},
|
|
310
|
+
styleControls: [
|
|
311
|
+
{ control: "spacing", styleKey: "padding", label: "Padding" },
|
|
312
|
+
{ control: "spacing", styleKey: "margin", label: "Margin" }
|
|
313
|
+
],
|
|
314
|
+
render: ({ props, slots, className }) => /* @__PURE__ */ jsx6(
|
|
315
|
+
"div",
|
|
316
|
+
{
|
|
317
|
+
className,
|
|
318
|
+
"data-nx-query-loop": "preview",
|
|
319
|
+
style: loopGridStyle(props),
|
|
320
|
+
children: slots.default
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// src/render/query/QueryLoopView.tsx
|
|
326
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
327
|
+
function QueryLoopView({
|
|
328
|
+
node,
|
|
329
|
+
registry,
|
|
330
|
+
dataProvider,
|
|
331
|
+
className,
|
|
332
|
+
result,
|
|
333
|
+
budget
|
|
334
|
+
}) {
|
|
335
|
+
const template = node.slots?.[DEFAULT_SLOT] ?? [];
|
|
336
|
+
if (result.skipped) {
|
|
337
|
+
return /* @__PURE__ */ jsx7("div", { className, "data-nx-query-loop": "config", children: "Configure a collection to load entries." });
|
|
338
|
+
}
|
|
339
|
+
if (result.error) {
|
|
340
|
+
return /* @__PURE__ */ jsx7("div", { className, "data-nx-query-loop": "error", children: "Could not load entries." });
|
|
341
|
+
}
|
|
342
|
+
if (result.items.length === 0) {
|
|
343
|
+
return /* @__PURE__ */ jsx7("div", { className, "data-nx-query-loop": "empty", children: "No entries found." });
|
|
344
|
+
}
|
|
345
|
+
return /* @__PURE__ */ jsx7(
|
|
346
|
+
"div",
|
|
347
|
+
{
|
|
348
|
+
className,
|
|
349
|
+
"data-nx-query-loop": "list",
|
|
350
|
+
style: loopGridStyle(node.props),
|
|
351
|
+
children: result.items.map((item, i) => /* @__PURE__ */ jsx7(
|
|
352
|
+
"div",
|
|
353
|
+
{
|
|
354
|
+
"data-nx-loop-item": i,
|
|
355
|
+
children: template.map((child) => /* @__PURE__ */ jsx7(
|
|
356
|
+
RenderNode,
|
|
357
|
+
{
|
|
358
|
+
node: child,
|
|
359
|
+
registry,
|
|
360
|
+
dataProvider,
|
|
361
|
+
item,
|
|
362
|
+
budget
|
|
363
|
+
},
|
|
364
|
+
child.id
|
|
365
|
+
))
|
|
366
|
+
},
|
|
367
|
+
typeof item.id === "string" ? item.id : i
|
|
368
|
+
))
|
|
369
|
+
}
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/render/query/runQuery.ts
|
|
374
|
+
async function runQuery(dataProvider, config, budget) {
|
|
375
|
+
if (!dataProvider || !config.collection) return { items: [], skipped: true };
|
|
376
|
+
if (budget.n <= 0) return { items: [], skipped: true };
|
|
377
|
+
budget.n -= 1;
|
|
378
|
+
try {
|
|
379
|
+
const { items } = await dataProvider.find({
|
|
380
|
+
collection: config.collection,
|
|
381
|
+
where: config.where,
|
|
382
|
+
sort: config.sort,
|
|
383
|
+
limit: typeof config.limit === "number" ? config.limit : void 0,
|
|
384
|
+
populate: config.populate
|
|
385
|
+
});
|
|
386
|
+
return { items: Array.isArray(items) ? items : [] };
|
|
387
|
+
} catch (err) {
|
|
388
|
+
return {
|
|
389
|
+
items: [],
|
|
390
|
+
error: err instanceof Error ? err.message : String(err)
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/render/query/QueryLoop.tsx
|
|
396
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
397
|
+
async function QueryLoop({
|
|
398
|
+
node,
|
|
399
|
+
registry,
|
|
400
|
+
dataProvider,
|
|
401
|
+
className,
|
|
402
|
+
budget
|
|
403
|
+
}) {
|
|
404
|
+
const config = node.props;
|
|
405
|
+
const result = await runQuery(dataProvider, config, budget);
|
|
406
|
+
return /* @__PURE__ */ jsx8(
|
|
407
|
+
QueryLoopView,
|
|
408
|
+
{
|
|
409
|
+
node,
|
|
410
|
+
registry,
|
|
411
|
+
dataProvider,
|
|
412
|
+
className,
|
|
413
|
+
result,
|
|
414
|
+
budget
|
|
415
|
+
}
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// src/render/query/types.ts
|
|
420
|
+
var QUERY_LOOP_TYPE = "core/query-loop";
|
|
421
|
+
var DEFAULT_QUERY_BUDGET = 20;
|
|
422
|
+
|
|
423
|
+
// src/render/RenderNode.tsx
|
|
424
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
425
|
+
function RenderNode({
|
|
426
|
+
node,
|
|
427
|
+
registry,
|
|
428
|
+
dataProvider,
|
|
429
|
+
item,
|
|
430
|
+
budget
|
|
431
|
+
}) {
|
|
432
|
+
const def = registry.get(node.type);
|
|
433
|
+
const className = [nodeClass(node.id), node.customClass].filter(Boolean).join(" ");
|
|
434
|
+
if (!def) {
|
|
435
|
+
return /* @__PURE__ */ jsx9("div", { "data-nx-unknown": node.type, className });
|
|
436
|
+
}
|
|
437
|
+
if (node.type === QUERY_LOOP_TYPE) {
|
|
438
|
+
return /* @__PURE__ */ jsx9(BlockErrorBoundary, { children: /* @__PURE__ */ jsx9(
|
|
439
|
+
QueryLoop,
|
|
440
|
+
{
|
|
441
|
+
node,
|
|
442
|
+
registry,
|
|
443
|
+
dataProvider,
|
|
444
|
+
className,
|
|
445
|
+
budget: budget ?? { n: 0 }
|
|
446
|
+
}
|
|
447
|
+
) });
|
|
448
|
+
}
|
|
449
|
+
const slots = {};
|
|
450
|
+
if (node.slots) {
|
|
451
|
+
for (const [name, children] of Object.entries(node.slots)) {
|
|
452
|
+
slots[name] = children.map((child) => /* @__PURE__ */ jsx9(
|
|
453
|
+
RenderNode,
|
|
454
|
+
{
|
|
455
|
+
node: child,
|
|
456
|
+
registry,
|
|
457
|
+
dataProvider,
|
|
458
|
+
item,
|
|
459
|
+
budget
|
|
460
|
+
},
|
|
461
|
+
child.id
|
|
462
|
+
));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
const props = item ? resolveBindings(node, item) : node.props;
|
|
466
|
+
return /* @__PURE__ */ jsx9(BlockErrorBoundary, { children: def.render({ props, node, slots, className }) });
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export {
|
|
470
|
+
paragraph,
|
|
471
|
+
heading,
|
|
472
|
+
image,
|
|
473
|
+
button,
|
|
474
|
+
video,
|
|
475
|
+
container,
|
|
476
|
+
grid,
|
|
477
|
+
loopGridStyle,
|
|
478
|
+
queryLoop,
|
|
479
|
+
QUERY_LOOP_TYPE,
|
|
480
|
+
DEFAULT_QUERY_BUDGET,
|
|
481
|
+
RenderNode
|
|
482
|
+
};
|
|
483
|
+
//# sourceMappingURL=chunk-R7YHOSL2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render/blocks/paragraph.tsx","../src/render/blocks/heading.tsx","../src/render/blocks/util.ts","../src/render/blocks/image.tsx","../src/render/blocks/button.tsx","../src/render/blocks/video.tsx","../src/render/blocks/container.tsx","../src/render/blocks/grid.tsx","../src/render/query/grid.ts","../src/render/blocks/queryLoop.tsx","../src/render/query/QueryLoopView.tsx","../src/render/query/runQuery.ts","../src/render/query/QueryLoop.tsx","../src/render/query/types.ts","../src/render/RenderNode.tsx"],"sourcesContent":["import { defineBlock } from \"../../core/registry\";\n\nexport const paragraph = defineBlock({\n type: \"core/paragraph\",\n version: 1,\n label: \"Paragraph\",\n icon: \"Type\",\n category: \"basic\",\n defaultProps: { text: \"New paragraph\" },\n contentFields: [\n { name: \"text\", type: \"textarea\", label: \"Text\", bindable: true },\n ],\n styleControls: [\n { control: \"color\", styleKey: \"color\", label: \"Text color\" },\n { control: \"dimension\", styleKey: \"fontSize\", label: \"Font size\" },\n { control: \"align\", styleKey: \"textAlign\", label: \"Align\" },\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, className }) => (\n <p className={className}>{String(props.text ?? \"\")}</p>\n ),\n});\n","import { createElement } from \"react\";\n\nimport { defineBlock } from \"../../core/registry\";\n\nconst LEVELS = [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"];\n\nexport const heading = defineBlock({\n type: \"core/heading\",\n version: 1,\n label: \"Heading\",\n icon: \"Heading\",\n category: \"basic\",\n defaultProps: { text: \"New heading\", level: \"h2\" },\n contentFields: [\n { name: \"text\", type: \"text\", label: \"Text\", bindable: true },\n {\n name: \"level\",\n type: \"select\",\n label: \"Level\",\n options: LEVELS.map(l => ({ value: l, label: l.toUpperCase() })),\n },\n ],\n styleControls: [\n { control: \"color\", styleKey: \"color\", label: \"Text color\" },\n { control: \"dimension\", styleKey: \"fontSize\", label: \"Font size\" },\n { control: \"align\", styleKey: \"textAlign\", label: \"Align\" },\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, className }) => {\n const level = LEVELS.includes(String(props.level))\n ? String(props.level)\n : \"h2\";\n return createElement(level, { className }, String(props.text ?? \"\"));\n },\n});\n","/**\n * Reject dangerous URL schemes for image/link/video srcs. Allows http(s)/relative/\n * mailto/tel. Browsers ignore ASCII control chars + whitespace when parsing a scheme\n * (so `java\\tscript:` still executes), so we strip those before testing — matching the\n * raw string alone is an XSS bypass.\n */\nexport function safeUrl(url: unknown): string | undefined {\n if (typeof url !== \"string\") return undefined;\n const trimmed = url.trim();\n if (!trimmed) return undefined;\n // Strip control chars (U+0000–U+0020, U+007F) + whitespace, then test the scheme.\n // eslint-disable-next-line no-control-regex\n const scheme = trimmed.replace(/[\\u0000-\\u0020\\u007f]+/g, \"\").toLowerCase();\n if (/^(javascript|vbscript|data):/.test(scheme)) return undefined;\n return trimmed;\n}\n","import { defineBlock } from \"../../core/registry\";\n\nimport { safeUrl } from \"./util\";\n\ninterface MediaValue {\n mediaId?: string;\n url?: string;\n alt?: string;\n width?: number;\n height?: number;\n}\n\ninterface ImageProps extends MediaValue {\n /** Editor-populated media object (from the media control). */\n media?: MediaValue;\n}\n\nexport const image = defineBlock<ImageProps>({\n type: \"core/image\",\n version: 1,\n label: \"Image\",\n icon: \"Image\",\n category: \"media\",\n defaultProps: { url: \"\", alt: \"\" },\n contentFields: [\n { name: \"media\", type: \"media\", label: \"Image\", bindable: true },\n ],\n styleControls: [\n { control: \"dimension\", styleKey: \"width\", label: \"Width\" },\n { control: \"dimension\", styleKey: \"borderRadius\", label: \"Radius\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, className }) => {\n // `media` may be the editor's media object, or — when bound to a Query Loop item's\n // field — a `{ url }` object or a plain URL string; normalize all three.\n const raw: unknown = props.media;\n const media: MediaValue =\n typeof raw === \"string\" ? { url: raw } : ((raw as MediaValue) ?? {});\n const src = safeUrl(media.url ?? props.url);\n if (!src) return null;\n const alt = media.alt ?? props.alt;\n const width = media.width ?? props.width;\n const height = media.height ?? props.height;\n return (\n <img\n className={className}\n src={src}\n alt={typeof alt === \"string\" ? alt : \"\"}\n width={typeof width === \"number\" ? width : undefined}\n height={typeof height === \"number\" ? height : undefined}\n loading=\"lazy\"\n />\n );\n },\n});\n","import { defineBlock } from \"../../core/registry\";\n\nimport { safeUrl } from \"./util\";\n\nexport const button = defineBlock({\n type: \"core/button\",\n version: 1,\n label: \"Button\",\n icon: \"MousePointerClick\",\n category: \"basic\",\n defaultProps: { text: \"Click me\", link: { href: \"\", target: \"\" } },\n contentFields: [\n { name: \"text\", type: \"text\", label: \"Label\", bindable: true },\n { name: \"link\", type: \"link\", label: \"Link\" },\n ],\n styleControls: [\n { control: \"color\", styleKey: \"color\", label: \"Text color\" },\n { control: \"color\", styleKey: \"backgroundColor\", label: \"Background\" },\n { control: \"dimension\", styleKey: \"borderRadius\", label: \"Radius\" },\n { control: \"align\", styleKey: \"textAlign\", label: \"Align\" },\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, className }) => {\n const link = (props.link ?? {}) as { href?: string; target?: string };\n const href = safeUrl(link.href);\n const text = String(props.text ?? \"Button\");\n if (!href) {\n return (\n <button className={className} type=\"button\">\n {text}\n </button>\n );\n }\n const target = link.target || undefined;\n return (\n <a\n className={className}\n href={href}\n target={target}\n rel={target === \"_blank\" ? \"noopener noreferrer\" : undefined}\n >\n {text}\n </a>\n );\n },\n});\n","import { defineBlock } from \"../../core/registry\";\n\nfunction embedUrl(provider: string, id: string): string | null {\n const safeId = encodeURIComponent(id);\n if (provider === \"youtube\") return `https://www.youtube.com/embed/${safeId}`;\n if (provider === \"vimeo\") return `https://player.vimeo.com/video/${safeId}`;\n return null;\n}\n\nexport const video = defineBlock({\n type: \"core/video\",\n version: 1,\n label: \"Video\",\n icon: \"Video\",\n category: \"media\",\n defaultProps: { provider: \"youtube\", videoId: \"\" },\n contentFields: [\n {\n name: \"provider\",\n type: \"select\",\n label: \"Provider\",\n options: [\n { value: \"youtube\", label: \"YouTube\" },\n { value: \"vimeo\", label: \"Vimeo\" },\n ],\n },\n {\n name: \"videoId\",\n type: \"text\",\n label: \"Video ID\",\n placeholder: \"e.g. dQw4w9WgXcQ\",\n },\n ],\n styleControls: [\n { control: \"dimension\", styleKey: \"maxWidth\", label: \"Max width\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, className }) => {\n const provider = String(props.provider ?? \"\");\n const id = typeof props.videoId === \"string\" ? props.videoId.trim() : \"\";\n const src = id ? embedUrl(provider, id) : null;\n if (!src) return null;\n return (\n <div className={className}>\n <iframe\n src={src}\n title=\"Embedded video\"\n allowFullScreen\n style={{ border: 0, width: \"100%\", aspectRatio: \"16 / 9\" }}\n />\n </div>\n );\n },\n});\n","import { createElement } from \"react\";\n\nimport { defineBlock } from \"../../core/registry\";\n\nconst TAGS = [\"section\", \"div\", \"article\", \"header\", \"footer\", \"aside\"];\n\nexport const container = defineBlock({\n type: \"core/container\",\n version: 1,\n label: \"Container\",\n icon: \"Square\",\n category: \"layout\",\n isContainer: true,\n slots: [{ name: \"default\" }],\n defaultProps: { as: \"section\" },\n contentFields: [\n {\n name: \"as\",\n type: \"select\",\n label: \"HTML tag\",\n options: TAGS.map(t => ({ value: t, label: t })),\n },\n ],\n styleControls: [\n { control: \"color\", styleKey: \"backgroundColor\", label: \"Background\" },\n { control: \"dimension\", styleKey: \"maxWidth\", label: \"Max width\" },\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n { control: \"dimension\", styleKey: \"borderRadius\", label: \"Radius\" },\n ],\n render: ({ props, slots, className }) => {\n const tag = TAGS.includes(String(props.as)) ? String(props.as) : \"section\";\n return createElement(tag, { className }, slots.default);\n },\n});\n","import { defineBlock } from \"../../core/registry\";\n\n// Grid layout: the column count + gap are driven by the `columns`/`gap` content fields and\n// applied as an inline grid style (safe: CSS values in a style object are never executed).\n// Colours/spacing/etc. still come from the style compiler via `className`.\ninterface GridProps {\n columns?: number;\n gap?: string;\n}\n\nexport const grid = defineBlock<GridProps>({\n type: \"core/grid\",\n version: 1,\n label: \"Grid\",\n icon: \"LayoutGrid\",\n category: \"layout\",\n isContainer: true,\n slots: [{ name: \"default\" }],\n defaultProps: { columns: 2, gap: \"16px\" },\n contentFields: [\n { name: \"columns\", type: \"number\", label: \"Columns\" },\n { name: \"gap\", type: \"text\", label: \"Gap\", placeholder: \"16px\" },\n ],\n styleControls: [\n { control: \"color\", styleKey: \"backgroundColor\", label: \"Background\" },\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, slots, className }) => {\n const columns =\n typeof props.columns === \"number\" && props.columns > 0\n ? Math.min(props.columns, 12)\n : 2;\n const gap = typeof props.gap === \"string\" ? props.gap : \"16px\";\n return (\n <div\n className={className}\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n gap,\n }}\n >\n {slots.default}\n </div>\n );\n },\n});\n","/**\n * Query Loop layout: turn the `columns`/`gap` props into a grid style so the loop reads as\n * a grid (Elementor's Loop Grid). `columns <= 1` returns undefined (plain stacked list, no\n * grid box). Shared by the production view, the design-time preview, and the canvas preview.\n */\nimport type { CSSProperties } from \"react\";\n\nexport function loopGridStyle(\n props: Record<string, unknown>\n): CSSProperties | undefined {\n const raw = typeof props.columns === \"number\" ? props.columns : 1;\n const columns = raw > 1 ? Math.min(Math.floor(raw), 12) : 0;\n if (!columns) return undefined;\n const gap = typeof props.gap === \"string\" ? props.gap : \"16px\";\n return {\n display: \"grid\",\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n gap,\n };\n}\n","import { defineBlock } from \"../../core/registry\";\nimport { loopGridStyle } from \"../query/grid\";\n\n/**\n * Query Loop block (spec §10/§5). At production render, RenderNode intercepts this type and\n * renders it data-driven via QueryLoop. The editor uses a dedicated settings panel + a live\n * sample-data preview (see admin). This `render` is the plain design-time fallback: the\n * template laid out in the configured column grid.\n *\n * Config lives in `props` (collection / sort / limit / columns / gap / where) and is driven\n * by the admin's QueryLoopSettings panel rather than generic content fields.\n */\nexport const queryLoop = defineBlock({\n type: \"core/query-loop\",\n version: 1,\n label: \"Query Loop\",\n icon: \"Repeat\",\n category: \"dynamic\",\n isContainer: true,\n slots: [{ name: \"default\" }],\n defaultProps: {\n collection: \"\",\n sort: \"\",\n limit: 10,\n columns: 1,\n gap: \"16px\",\n },\n styleControls: [\n { control: \"spacing\", styleKey: \"padding\", label: \"Padding\" },\n { control: \"spacing\", styleKey: \"margin\", label: \"Margin\" },\n ],\n render: ({ props, slots, className }) => (\n <div\n className={className}\n data-nx-query-loop=\"preview\"\n style={loopGridStyle(props)}\n >\n {slots.default}\n </div>\n ),\n});\n","/**\n * Synchronous view for the Query Loop (spec §10). Given an already-resolved QueryResult,\n * it renders the config / error / empty state, or expands the template slot once per item\n * — threading each `item` into RenderNode so bound props resolve at any depth. Sync so it\n * is testable via renderToStaticMarkup; the async fetch lives in QueryLoop.\n */\nimport type { ReactNode } from \"react\";\n\nimport type { BlockRegistry } from \"../../core/registry\";\nimport { DEFAULT_SLOT, type BlockNode } from \"../../core/types\";\nimport type { DataProvider } from \"../dataProvider\";\nimport { RenderNode } from \"../RenderNode\";\n\nimport { loopGridStyle } from \"./grid\";\nimport type { QueryBudget } from \"./runQuery\";\nimport type { QueryResult } from \"./types\";\n\nexport interface QueryLoopViewProps {\n node: BlockNode;\n registry: BlockRegistry;\n dataProvider?: DataProvider;\n className: string;\n result: QueryResult;\n budget: QueryBudget;\n}\n\nexport function QueryLoopView({\n node,\n registry,\n dataProvider,\n className,\n result,\n budget,\n}: QueryLoopViewProps): ReactNode {\n const template = node.slots?.[DEFAULT_SLOT] ?? [];\n\n if (result.skipped) {\n return (\n <div className={className} data-nx-query-loop=\"config\">\n Configure a collection to load entries.\n </div>\n );\n }\n if (result.error) {\n return (\n <div className={className} data-nx-query-loop=\"error\">\n Could not load entries.\n </div>\n );\n }\n if (result.items.length === 0) {\n return (\n <div className={className} data-nx-query-loop=\"empty\">\n No entries found.\n </div>\n );\n }\n\n return (\n <div\n className={className}\n data-nx-query-loop=\"list\"\n style={loopGridStyle(node.props)}\n >\n {result.items.map((item, i) => (\n <div\n key={typeof item.id === \"string\" ? item.id : i}\n data-nx-loop-item={i}\n >\n {template.map(child => (\n <RenderNode\n key={child.id}\n node={child}\n registry={registry}\n dataProvider={dataProvider}\n item={item}\n budget={budget}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n","/**\n * Async fetch orchestration for the Query Loop (spec §10). Isolated from React so it is\n * unit-testable. Enforces the per-render query budget, skips when unconfigured, and\n * converts provider failures into an error state instead of throwing.\n */\nimport type { DataProvider } from \"../dataProvider\";\n\nimport type { QueryLoopConfig, QueryResult } from \"./types\";\n\nexport interface QueryBudget {\n n: number;\n}\n\nexport async function runQuery(\n dataProvider: DataProvider | undefined,\n config: QueryLoopConfig,\n budget: QueryBudget\n): Promise<QueryResult> {\n if (!dataProvider || !config.collection) return { items: [], skipped: true };\n if (budget.n <= 0) return { items: [], skipped: true };\n budget.n -= 1;\n try {\n const { items } = await dataProvider.find({\n collection: config.collection,\n where: config.where,\n sort: config.sort,\n limit: typeof config.limit === \"number\" ? config.limit : undefined,\n populate: config.populate,\n });\n return { items: Array.isArray(items) ? items : [] };\n } catch (err) {\n return {\n items: [],\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","/**\n * Async server component for the Query Loop (spec §10). Fetches entries via the injected\n * dataProvider (bounded by the shared query budget), then delegates to the synchronous\n * QueryLoopView. Rendered only on the server (RenderNode intercepts `core/query-loop`);\n * never imports `getNextly`.\n */\nimport type { ReactNode } from \"react\";\n\nimport type { BlockRegistry } from \"../../core/registry\";\nimport type { BlockNode } from \"../../core/types\";\nimport type { DataProvider } from \"../dataProvider\";\n\nimport { QueryLoopView } from \"./QueryLoopView\";\nimport { runQuery, type QueryBudget } from \"./runQuery\";\nimport type { QueryLoopConfig } from \"./types\";\n\nexport interface QueryLoopProps {\n node: BlockNode;\n registry: BlockRegistry;\n dataProvider?: DataProvider;\n className: string;\n budget: QueryBudget;\n}\n\nexport async function QueryLoop({\n node,\n registry,\n dataProvider,\n className,\n budget,\n}: QueryLoopProps): Promise<ReactNode> {\n const config = node.props as QueryLoopConfig;\n const result = await runQuery(dataProvider, config, budget);\n return (\n <QueryLoopView\n node={node}\n registry={registry}\n dataProvider={dataProvider}\n className={className}\n result={result}\n budget={budget}\n />\n );\n}\n","/**\n * Executable Query Loop contracts (spec §10). Kept React-free so the fetch orchestration\n * and config stay unit-testable and import-safe.\n */\nexport const QUERY_LOOP_TYPE = \"core/query-loop\";\n\n/** Max collection fetches per page render — bounds nested loops (with MAX_DEPTH). */\nexport const DEFAULT_QUERY_BUDGET = 20;\n\nexport interface QueryLoopConfig {\n collection?: string;\n sort?: string;\n limit?: number;\n /** Reserved: passed through to the provider's `where`. */\n where?: unknown;\n /** Reserved: relation/media population depth. */\n populate?: unknown;\n}\n\nexport interface QueryResult {\n items: Record<string, unknown>[];\n error?: string;\n /** True when the query was skipped (no provider / no collection / budget spent). */\n skipped?: boolean;\n}\n","/**\n * Recursively renders one block node to React (spec §10). Server-safe: no browser\n * globals, no `getNextly`. The scoped class is applied to the block's OWN root element\n * (the block spreads `className`) so there is no mandatory wrapper `<div>` — grid/flex\n * stay correct. Unknown block types render a safe fallback; each node is isolated by an\n * error boundary so one broken block never takes down the page.\n *\n * Query Loop (spec §10): the current loop `item` is threaded through recursion (NOT React\n * context — Server Components can't consume context), so a bound prop on any nested block\n * at any depth resolves via `resolveBindings`. `core/query-loop` is intercepted and\n * rendered data-driven via `QueryLoop`.\n */\nimport type { ReactNode } from \"react\";\n\nimport { resolveBindings } from \"../core/bindings\";\nimport type { BlockRegistry } from \"../core/registry\";\nimport { nodeClass } from \"../core/style-compiler\";\nimport type { BlockNode } from \"../core/types\";\n\nimport type { DataProvider } from \"./dataProvider\";\nimport { BlockErrorBoundary } from \"./ErrorBoundary\";\nimport { QueryLoop } from \"./query/QueryLoop\";\nimport type { QueryBudget } from \"./query/runQuery\";\nimport { QUERY_LOOP_TYPE } from \"./query/types\";\n\nexport interface RenderNodeProps {\n node: BlockNode;\n registry: BlockRegistry;\n dataProvider?: DataProvider;\n /** Current Query Loop item — threaded to resolve bindings at any depth. */\n item?: Record<string, unknown>;\n /** Remaining query budget shared across nested loops on this page render. */\n budget?: QueryBudget;\n}\n\nexport function RenderNode({\n node,\n registry,\n dataProvider,\n item,\n budget,\n}: RenderNodeProps): ReactNode {\n const def = registry.get(node.type);\n const className = [nodeClass(node.id), node.customClass]\n .filter(Boolean)\n .join(\" \");\n\n if (!def) {\n // Preserve, don't crash: a placeholder that keeps the page rendering.\n return <div data-nx-unknown={node.type} className={className} />;\n }\n\n // Executable Query Loop: intercept and render data-driven (spec §10).\n if (node.type === QUERY_LOOP_TYPE) {\n return (\n <BlockErrorBoundary>\n <QueryLoop\n node={node}\n registry={registry}\n dataProvider={dataProvider}\n className={className}\n budget={budget ?? { n: 0 }}\n />\n </BlockErrorBoundary>\n );\n }\n\n const slots: Record<string, ReactNode> = {};\n if (node.slots) {\n for (const [name, children] of Object.entries(node.slots)) {\n slots[name] = children.map(child => (\n <RenderNode\n key={child.id}\n node={child}\n registry={registry}\n dataProvider={dataProvider}\n item={item}\n budget={budget}\n />\n ));\n }\n }\n\n const props = item ? resolveBindings(node, item) : node.props;\n\n return (\n <BlockErrorBoundary>\n {def.render({ props, node, slots, className })}\n </BlockErrorBoundary>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","createElement","createElement","jsx","jsx","jsx","jsx","jsx"]}
|